2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
4 * Copyright (C) 2005 Luca Ognibene <luogni@tin.it>
5 * Copyright (C) 2006 Martin Zlomek <martin.zlomek@itonis.tv>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
27 #ifdef HAVE_FFMPEG_UNINSTALLED
30 #include <libavcodec/avcodec.h>
34 #include <gst/base/gstbasetransform.h>
35 #include <gst/video/video.h>
37 #include "gstffmpeg.h"
38 #include "gstffmpegcodecmap.h"
40 typedef struct _GstFFMpegAudioResample
42 GstBaseTransform element;
44 GstPad *sinkpad, *srcpad;
46 gint in_rate, out_rate;
47 gint in_channels, out_channels;
50 } GstFFMpegAudioResample;
52 typedef struct _GstFFMpegAudioResampleClass
54 GstBaseTransformClass parent_class;
55 } GstFFMpegAudioResampleClass;
57 #define GST_TYPE_FFMPEGAUDIORESAMPLE \
58 (gst_ffmpegaudioresample_get_type())
59 #define GST_FFMPEGAUDIORESAMPLE(obj) \
60 (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FFMPEGAUDIORESAMPLE,GstFFMpegAudioResample))
61 #define GST_FFMPEGAUDIORESAMPLE_CLASS(klass) \
62 (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FFMPEGAUDIORESAMPLE,GstFFMpegAudioResampleClass))
63 #define GST_IS_FFMPEGAUDIORESAMPLE(obj) \
64 (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FFMPEGAUDIORESAMPLE))
65 #define GST_IS_FFMPEGAUDIORESAMPLE_CLASS(klass) \
66 (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FFMPEGAUDIORESAMPLE))
68 GType gst_ffmpegaudioresample_get_type (void);
70 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
74 ("audio/x-raw-int, endianness = (int) BYTE_ORDER, signed = (boolean) true, width = (int) 16, depth = (int) 16, channels = (int) { 1 , 2 }, rate = (int) [1, MAX ]")
77 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
81 ("audio/x-raw-int, endianness = (int) BYTE_ORDER, signed = (boolean) true, width = (int) 16, depth = (int) 16, channels = (int) [ 1 , 6 ], rate = (int) [1, MAX ]")
84 GST_BOILERPLATE (GstFFMpegAudioResample, gst_ffmpegaudioresample,
85 GstBaseTransform, GST_TYPE_BASE_TRANSFORM);
87 static void gst_ffmpegaudioresample_finalize (GObject * object);
89 static GstCaps *gst_ffmpegaudioresample_transform_caps (GstBaseTransform *
90 trans, GstPadDirection direction, GstCaps * caps);
91 static gboolean gst_ffmpegaudioresample_transform_size (GstBaseTransform *
92 trans, GstPadDirection direction, GstCaps * caps, guint size,
93 GstCaps * othercaps, guint * othersize);
94 static gboolean gst_ffmpegaudioresample_get_unit_size (GstBaseTransform * trans,
95 GstCaps * caps, guint * size);
96 static gboolean gst_ffmpegaudioresample_set_caps (GstBaseTransform * trans,
97 GstCaps * incaps, GstCaps * outcaps);
98 static GstFlowReturn gst_ffmpegaudioresample_transform (GstBaseTransform *
99 trans, GstBuffer * inbuf, GstBuffer * outbuf);
102 gst_ffmpegaudioresample_base_init (gpointer g_class)
104 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
106 gst_element_class_add_pad_template (element_class,
107 gst_static_pad_template_get (&src_factory));
108 gst_element_class_add_pad_template (element_class,
109 gst_static_pad_template_get (&sink_factory));
110 gst_element_class_set_details_simple (element_class,
111 "FFMPEG Audio resampling element", "Filter/Converter/Audio",
112 "Converts audio from one samplerate to another",
113 "Edward Hervey <bilboed@bilboed.com>");
117 gst_ffmpegaudioresample_class_init (GstFFMpegAudioResampleClass * klass)
119 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
120 GstBaseTransformClass *trans_class = GST_BASE_TRANSFORM_CLASS (klass);
122 gobject_class->finalize = gst_ffmpegaudioresample_finalize;
124 trans_class->transform_caps =
125 GST_DEBUG_FUNCPTR (gst_ffmpegaudioresample_transform_caps);
126 trans_class->get_unit_size =
127 GST_DEBUG_FUNCPTR (gst_ffmpegaudioresample_get_unit_size);
128 trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_ffmpegaudioresample_set_caps);
129 trans_class->transform =
130 GST_DEBUG_FUNCPTR (gst_ffmpegaudioresample_transform);
131 trans_class->transform_size =
132 GST_DEBUG_FUNCPTR (gst_ffmpegaudioresample_transform_size);
134 trans_class->passthrough_on_same_caps = TRUE;
138 gst_ffmpegaudioresample_init (GstFFMpegAudioResample * resample,
139 GstFFMpegAudioResampleClass * klass)
141 GstBaseTransform *trans = GST_BASE_TRANSFORM (resample);
143 gst_pad_set_bufferalloc_function (trans->sinkpad, NULL);
145 resample->res = NULL;
149 gst_ffmpegaudioresample_finalize (GObject * object)
151 GstFFMpegAudioResample *resample = GST_FFMPEGAUDIORESAMPLE (object);
153 if (resample->res != NULL)
154 audio_resample_close (resample->res);
156 G_OBJECT_CLASS (parent_class)->finalize (object);
160 gst_ffmpegaudioresample_transform_caps (GstBaseTransform * trans,
161 GstPadDirection direction, GstCaps * caps)
166 retcaps = gst_caps_copy (caps);
167 struc = gst_caps_get_structure (retcaps, 0);
168 gst_structure_set (struc, "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL);
170 GST_LOG_OBJECT (trans, "returning caps %" GST_PTR_FORMAT, retcaps);
176 gst_ffmpegaudioresample_transform_size (GstBaseTransform * trans,
177 GstPadDirection direction, GstCaps * caps, guint size, GstCaps * othercaps,
180 gint inrate, outrate;
181 gint inchanns, outchanns;
182 GstStructure *ins, *outs;
186 ins = gst_caps_get_structure (caps, 0);
187 outs = gst_caps_get_structure (othercaps, 0);
189 /* Get input/output sample rate and channels */
190 ret = gst_structure_get_int (ins, "rate", &inrate);
191 ret &= gst_structure_get_int (ins, "channels", &inchanns);
192 ret &= gst_structure_get_int (outs, "rate", &outrate);
193 ret &= gst_structure_get_int (outs, "channels", &outchanns);
198 conv = gst_util_uint64_scale (size, outrate * outchanns, inrate * inchanns);
199 /* Adding padding to the output buffer size, since audio_resample's internal
200 * methods might write a bit further. */
201 *othersize = (guint) conv + 64;
203 GST_DEBUG_OBJECT (trans, "Transformed size from %d to %d", size, *othersize);
209 gst_ffmpegaudioresample_get_unit_size (GstBaseTransform * trans, GstCaps * caps,
213 GstStructure *structure;
218 structure = gst_caps_get_structure (caps, 0);
219 ret = gst_structure_get_int (structure, "channels", &channels);
220 g_return_val_if_fail (ret, FALSE);
222 *size = 2 * channels;
228 gst_ffmpegaudioresample_set_caps (GstBaseTransform * trans, GstCaps * incaps,
231 GstFFMpegAudioResample *resample = GST_FFMPEGAUDIORESAMPLE (trans);
232 GstStructure *instructure = gst_caps_get_structure (incaps, 0);
233 GstStructure *outstructure = gst_caps_get_structure (outcaps, 0);
235 GST_LOG_OBJECT (resample, "incaps:%" GST_PTR_FORMAT, incaps);
237 GST_LOG_OBJECT (resample, "outcaps:%" GST_PTR_FORMAT, outcaps);
239 if (!gst_structure_get_int (instructure, "channels", &resample->in_channels))
241 if (!gst_structure_get_int (instructure, "rate", &resample->in_rate))
244 if (!gst_structure_get_int (outstructure, "channels",
245 &resample->out_channels))
247 if (!gst_structure_get_int (outstructure, "rate", &resample->out_rate))
251 audio_resample_init (resample->out_channels, resample->in_channels,
252 resample->out_rate, resample->in_rate);
253 if (resample->res == NULL)
260 gst_ffmpegaudioresample_transform (GstBaseTransform * trans, GstBuffer * inbuf,
263 GstFFMpegAudioResample *resample = GST_FFMPEGAUDIORESAMPLE (trans);
267 gst_buffer_copy_metadata (outbuf, inbuf, GST_BUFFER_COPY_TIMESTAMPS);
268 nbsamples = GST_BUFFER_SIZE (inbuf) / (2 * resample->in_channels);
270 GST_LOG_OBJECT (resample, "input buffer duration:%" GST_TIME_FORMAT,
271 GST_TIME_ARGS (GST_BUFFER_DURATION (inbuf)));
273 GST_DEBUG_OBJECT (resample,
274 "audio_resample(ctx, output:%p [size:%d], input:%p [size:%d], nbsamples:%d",
275 GST_BUFFER_DATA (outbuf), GST_BUFFER_SIZE (outbuf),
276 GST_BUFFER_DATA (inbuf), GST_BUFFER_SIZE (inbuf), nbsamples);
278 ret = audio_resample (resample->res, (short *) GST_BUFFER_DATA (outbuf),
279 (short *) GST_BUFFER_DATA (inbuf), nbsamples);
281 GST_DEBUG_OBJECT (resample, "audio_resample returned %d", ret);
283 GST_BUFFER_DURATION (outbuf) = gst_util_uint64_scale (ret, GST_SECOND,
285 GST_BUFFER_SIZE (outbuf) = ret * 2 * resample->out_channels;
287 GST_LOG_OBJECT (resample, "Output buffer duration:%" GST_TIME_FORMAT,
288 GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)));
294 gst_ffmpegaudioresample_register (GstPlugin * plugin)
296 return gst_element_register (plugin, "ffaudioresample",
297 GST_RANK_NONE, GST_TYPE_FFMPEGAUDIORESAMPLE);