aboutsummaryrefslogtreecommitdiff
path: root/src/filter/volume_filter_plugin.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/filter/volume_filter_plugin.c')
-rw-r--r--src/filter/volume_filter_plugin.c101
1 files changed, 55 insertions, 46 deletions
diff --git a/src/filter/volume_filter_plugin.c b/src/filter/volume_filter_plugin.c
index e52c0a46..27276998 100644
--- a/src/filter/volume_filter_plugin.c
+++ b/src/filter/volume_filter_plugin.c
@@ -23,7 +23,6 @@
#include "filter_internal.h"
#include "filter_registry.h"
#include "conf.h"
-#include "pcm_buffer.h"
#include "pcm_volume.h"
#include "audio_format.h"
#include "player_control.h"
@@ -31,6 +30,10 @@
#include <assert.h>
#include <string.h>
+#include <libavutil/channel_layout.h>
+#include <libavutil/frame.h>
+#include <libavutil/samplefmt.h>
+
struct volume_filter {
struct filter filter;
@@ -40,8 +43,6 @@ struct volume_filter {
unsigned volume;
struct audio_format audio_format;
-
- struct pcm_buffer buffer;
};
static inline GQuark
@@ -75,54 +76,63 @@ volume_filter_open(struct filter *_filter, struct audio_format *audio_format,
struct volume_filter *filter = (struct volume_filter *)_filter;
filter->audio_format = *audio_format;
- pcm_buffer_init(&filter->buffer);
return &filter->audio_format;
}
-static void
-volume_filter_close(struct filter *_filter)
-{
- struct volume_filter *filter = (struct volume_filter *)_filter;
-
- pcm_buffer_deinit(&filter->buffer);
-}
-
-static const void *
-volume_filter_filter(struct filter *_filter, const void *src, size_t src_size,
- size_t *dest_size_r, GError **error_r)
+static AVFrame *volume_filter_filter(struct filter *_filter, AVFrame *src)
{
struct volume_filter *filter = (struct volume_filter *)_filter;
- bool success;
- void *dest;
-
- *dest_size_r = src_size;
-
- if (filter->volume >= PCM_VOLUME_1)
- /* optimized special case: 100% volume = no-op */
- return src;
-
- dest = pcm_buffer_get(&filter->buffer, src_size);
-
- if (filter->volume <= 0) {
- /* optimized special case: 0% volume = memset(0) */
- /* XXX is this valid for all sample formats? What
- about floating point? */
- memset(dest, 0, src_size);
- return dest;
- }
-
- memcpy(dest, src, src_size);
-
- success = pcm_volume(dest, src_size, filter->audio_format.format,
- filter->volume);
- if (!success) {
- g_set_error(error_r, volume_quark(), 0,
- "pcm_volume() has failed");
- return NULL;
- }
-
- return dest;
+ int planar = av_sample_fmt_is_planar(src->format);
+ int planes = planar ? av_get_channel_layout_nb_channels(src->channel_layout) : 1;
+ int ret, i;
+
+ /* optimized special case: 100% volume = no-op */
+ if (filter->volume == PCM_VOLUME_1)
+ return src;
+
+ /* optimized special case: 0% volume = memset(0) */
+ if (filter->volume <= 0) {
+ AVFrame *dst = av_frame_alloc();
+ if (!dst) {
+ av_frame_free(&src);
+ return NULL;
+ }
+
+ dst->nb_samples = src->nb_samples;
+ dst->format = src->format;
+ dst->channel_layout = src->channel_layout;
+ av_frame_copy_props(dst, src);
+ av_frame_free(&src);
+
+ ret = av_frame_get_buffer(dst, 32);
+ if (ret < 0)
+ return NULL;
+
+ av_samples_set_silence(dst->extended_data, 0, dst->nb_samples,
+ av_get_channel_layout_nb_channels(dst->channel_layout),
+ dst->format);
+ return dst;
+ }
+
+ ret = av_frame_make_writable(src);
+ if (ret < 0) {
+ av_frame_free(&src);
+ return NULL;
+ }
+
+ for (i = 0; i < planes; i++) {
+ ret = pcm_volume(src->extended_data[i], src->linesize[0],
+ av_get_packed_sample_fmt(filter->audio_format.format),
+ filter->volume);
+ if (!ret) {
+ g_warning("pcm_volume() has failed");
+ av_frame_free(&src);
+ return NULL;
+ }
+ }
+
+ return src;
}
const struct filter_plugin volume_filter_plugin = {
@@ -130,7 +140,6 @@ const struct filter_plugin volume_filter_plugin = {
.init = volume_filter_init,
.finish = volume_filter_finish,
.open = volume_filter_open,
- .close = volume_filter_close,
.filter = volume_filter_filter,
};