From 97becbc31bfd6acb76f584eaf65c1546d6fbcc8b Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 13 Jan 2015 20:14:25 +0100 Subject: audio: add some utility functions for refcounted frames Used in the following commits. --- audio/audio.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++--------- audio/audio.h | 6 ++++++ 2 files changed, 64 insertions(+), 10 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 93e9f1814b..57eb9ca20f 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -227,6 +227,14 @@ void mp_audio_copy(struct mp_audio *dst, int dst_offset, } } +// Copy fields that describe characteristics of the audio frame, but which are +// not part of the core format (format/channels/rate), and not part of the +// data (samples). +void mp_audio_copy_attributes(struct mp_audio *dst, struct mp_audio *src) +{ + // nothing yet +} + // Set data to the audio after the given number of samples (i.e. slice it). void mp_audio_skip_samples(struct mp_audio *data, int samples) { @@ -238,28 +246,40 @@ void mp_audio_skip_samples(struct mp_audio *data, int samples) data->samples -= samples; } -// Make sure the frame owns the audio data, and if not, copy the data. -// Return negative value on failure (which means it can't be made writeable). -// Non-refcounted frames are always considered writeable. -int mp_audio_make_writeable(struct mp_audio *data) +// Return false if the frame data is shared, true otherwise. +// Will return true for non-refcounted frames. +bool mp_audio_is_writeable(struct mp_audio *data) { bool ok = true; for (int n = 0; n < MP_NUM_CHANNELS; n++) { if (data->allocated[n]) ok &= av_buffer_is_writable(data->allocated[n]); } - if (!ok) { + return ok; +} + +static void mp_audio_steal_data(struct mp_audio *dst, struct mp_audio *src) +{ + talloc_set_destructor(dst, mp_audio_destructor); + mp_audio_destructor(dst); + *dst = *src; + talloc_set_destructor(src, NULL); + talloc_free(src); +} + +// Make sure the frame owns the audio data, and if not, copy the data. +// Return negative value on failure (which means it can't be made writeable). +// Non-refcounted frames are always considered writeable. +int mp_audio_make_writeable(struct mp_audio *data) +{ + if (!mp_audio_is_writeable(data)) { struct mp_audio *new = talloc(NULL, struct mp_audio); *new = *data; mp_audio_set_null_data(new); // use format only mp_audio_realloc(new, data->samples); new->samples = data->samples; mp_audio_copy(new, 0, data, 0, data->samples); - // "Transfer" the reference. - mp_audio_destructor(data); - *data = *new; - talloc_set_destructor(new, NULL); - talloc_free(new); + mp_audio_steal_data(data, new); } return 0; } @@ -370,3 +390,31 @@ struct mp_audio *mp_audio_pool_get(struct mp_audio_pool *pool, } return new; } + +// Return a copy of the given frame. +// Returns NULL on error. +struct mp_audio *mp_audio_pool_new_copy(struct mp_audio_pool *pool, + struct mp_audio *frame) +{ + struct mp_audio *new = mp_audio_pool_get(pool, frame, frame->samples); + if (new) { + mp_audio_copy(new, 0, frame, 0, new->samples); + mp_audio_copy_attributes(new, frame); + } + return new; +} + +// Exactly like mp_audio_make_writeable(), but get the data from the pool. +int mp_audio_pool_make_writeable(struct mp_audio_pool *pool, + struct mp_audio *data) +{ + if (mp_audio_is_writeable(data)) + return 0; + struct mp_audio *new = mp_audio_pool_get(pool, data, data->samples); + if (!new) + return -1; + mp_audio_copy(new, 0, data, 0, data->samples); + mp_audio_copy_attributes(new, data); + mp_audio_steal_data(data, new); + return 0; +} diff --git a/audio/audio.h b/audio/audio.h index e2346ee0aa..39ceb00705 100644 --- a/audio/audio.h +++ b/audio/audio.h @@ -66,8 +66,10 @@ void mp_audio_fill_silence(struct mp_audio *mpa, int start, int length); void mp_audio_copy(struct mp_audio *dst, int dst_offset, struct mp_audio *src, int src_offset, int length); +void mp_audio_copy_attributes(struct mp_audio *dst, struct mp_audio *src); void mp_audio_skip_samples(struct mp_audio *data, int samples); +bool mp_audio_is_writeable(struct mp_audio *data); int mp_audio_make_writeable(struct mp_audio *data); struct AVFrame; @@ -76,5 +78,9 @@ struct mp_audio *mp_audio_from_avframe(struct AVFrame *avframe); struct mp_audio_pool *mp_audio_pool_create(void *ta_parent); struct mp_audio *mp_audio_pool_get(struct mp_audio_pool *pool, const struct mp_audio *fmt, int samples); +struct mp_audio *mp_audio_pool_new_copy(struct mp_audio_pool *pool, + struct mp_audio *frame); +int mp_audio_pool_make_writeable(struct mp_audio_pool *pool, + struct mp_audio *frame); #endif -- cgit v1.2.3