~bluetooth/bluez/vivid-phone-overlay

« back to all changes in this revision

Viewing changes to audio/gstsbcdec.c

  • Committer: Simon Fels
  • Date: 2015-09-11 09:01:46 UTC
  • Revision ID: morphis@gravedo.de-20150911090146-4c0ln9s7ec3xf0nx
Import package bluez_4.101-0ubuntu25.1~overlay4 from stable phone overlay PPA

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *
 
3
 *  BlueZ - Bluetooth protocol stack for Linux
 
4
 *
 
5
 *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
 
6
 *
 
7
 *
 
8
 *  This library is free software; you can redistribute it and/or
 
9
 *  modify it under the terms of the GNU Lesser General Public
 
10
 *  License as published by the Free Software Foundation; either
 
11
 *  version 2.1 of the License, or (at your option) any later version.
 
12
 *
 
13
 *  This library is distributed in the hope that it will be useful,
 
14
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
16
 *  Lesser General Public License for more details.
 
17
 *
 
18
 *  You should have received a copy of the GNU Lesser General Public
 
19
 *  License along with this library; if not, write to the Free Software
 
20
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
21
 *
 
22
 */
 
23
 
 
24
#ifdef HAVE_CONFIG_H
 
25
#include <config.h>
 
26
#endif
 
27
 
 
28
#include <string.h>
 
29
 
 
30
#include "gstpragma.h"
 
31
#include "gstsbcutil.h"
 
32
#include "gstsbcdec.h"
 
33
 
 
34
GST_DEBUG_CATEGORY_STATIC(sbc_dec_debug);
 
35
#define GST_CAT_DEFAULT sbc_dec_debug
 
36
 
 
37
GST_BOILERPLATE(GstSbcDec, gst_sbc_dec, GstElement, GST_TYPE_ELEMENT);
 
38
 
 
39
static const GstElementDetails sbc_dec_details =
 
40
        GST_ELEMENT_DETAILS("Bluetooth SBC decoder",
 
41
                                "Codec/Decoder/Audio",
 
42
                                "Decode a SBC audio stream",
 
43
                                "Marcel Holtmann <marcel@holtmann.org>");
 
44
 
 
45
static GstStaticPadTemplate sbc_dec_sink_factory =
 
46
        GST_STATIC_PAD_TEMPLATE("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
 
47
                GST_STATIC_CAPS("audio/x-sbc"));
 
48
 
 
49
static GstStaticPadTemplate sbc_dec_src_factory =
 
50
        GST_STATIC_PAD_TEMPLATE("src", GST_PAD_SRC, GST_PAD_ALWAYS,
 
51
                GST_STATIC_CAPS("audio/x-raw-int, "
 
52
                                "rate = (int) { 16000, 32000, 44100, 48000 }, "
 
53
                                "channels = (int) [ 1, 2 ], "
 
54
                                "endianness = (int) BYTE_ORDER, "
 
55
                                "signed = (boolean) true, "
 
56
                                "width = (int) 16, "
 
57
                                "depth = (int) 16"));
 
58
 
 
59
static GstFlowReturn sbc_dec_chain(GstPad *pad, GstBuffer *buffer)
 
60
{
 
61
        GstSbcDec *dec = GST_SBC_DEC(gst_pad_get_parent(pad));
 
62
        GstFlowReturn res = GST_FLOW_OK;
 
63
        guint size, codesize, offset = 0;
 
64
        guint8 *data;
 
65
 
 
66
        codesize = sbc_get_codesize(&dec->sbc);
 
67
 
 
68
        if (dec->buffer) {
 
69
                GstBuffer *temp = buffer;
 
70
                buffer = gst_buffer_span(dec->buffer, 0, buffer,
 
71
                        GST_BUFFER_SIZE(dec->buffer) + GST_BUFFER_SIZE(buffer));
 
72
                gst_buffer_unref(temp);
 
73
                gst_buffer_unref(dec->buffer);
 
74
                dec->buffer = NULL;
 
75
        }
 
76
 
 
77
        data = GST_BUFFER_DATA(buffer);
 
78
        size = GST_BUFFER_SIZE(buffer);
 
79
 
 
80
        while (offset < size) {
 
81
                GstBuffer *output;
 
82
                GstPadTemplate *template;
 
83
                GstCaps *caps;
 
84
                int consumed;
 
85
 
 
86
                res = gst_pad_alloc_buffer_and_set_caps(dec->srcpad,
 
87
                                                GST_BUFFER_OFFSET_NONE,
 
88
                                                codesize, NULL, &output);
 
89
 
 
90
                if (res != GST_FLOW_OK)
 
91
                        goto done;
 
92
 
 
93
                consumed = sbc_decode(&dec->sbc, data + offset, size - offset,
 
94
                                        GST_BUFFER_DATA(output), codesize,
 
95
                                        NULL);
 
96
                if (consumed <= 0)
 
97
                        break;
 
98
 
 
99
                /* we will reuse the same caps object */
 
100
                if (dec->outcaps == NULL) {
 
101
                        caps = gst_caps_new_simple("audio/x-raw-int",
 
102
                                        "rate", G_TYPE_INT,
 
103
                                        gst_sbc_parse_rate_from_sbc(
 
104
                                                dec->sbc.frequency),
 
105
                                        "channels", G_TYPE_INT,
 
106
                                        gst_sbc_get_channel_number(
 
107
                                                dec->sbc.mode),
 
108
                                        NULL);
 
109
 
 
110
                        template = gst_static_pad_template_get(&sbc_dec_src_factory);
 
111
 
 
112
                        dec->outcaps = gst_caps_intersect(caps,
 
113
                                                gst_pad_template_get_caps(template));
 
114
 
 
115
                        gst_caps_unref(caps);
 
116
                }
 
117
 
 
118
                gst_buffer_set_caps(output, dec->outcaps);
 
119
 
 
120
                /* FIXME get a real timestamp */
 
121
                GST_BUFFER_TIMESTAMP(output) = GST_CLOCK_TIME_NONE;
 
122
 
 
123
                res = gst_pad_push(dec->srcpad, output);
 
124
                if (res != GST_FLOW_OK)
 
125
                        goto done;
 
126
 
 
127
                offset += consumed;
 
128
        }
 
129
 
 
130
        if (offset < size)
 
131
                dec->buffer = gst_buffer_create_sub(buffer,
 
132
                                                        offset, size - offset);
 
133
 
 
134
done:
 
135
        gst_buffer_unref(buffer);
 
136
        gst_object_unref(dec);
 
137
 
 
138
        return res;
 
139
}
 
140
 
 
141
static GstStateChangeReturn sbc_dec_change_state(GstElement *element,
 
142
                                                GstStateChange transition)
 
143
{
 
144
        GstSbcDec *dec = GST_SBC_DEC(element);
 
145
 
 
146
        switch (transition) {
 
147
        case GST_STATE_CHANGE_READY_TO_PAUSED:
 
148
                GST_DEBUG("Setup subband codec");
 
149
                if (dec->buffer) {
 
150
                        gst_buffer_unref(dec->buffer);
 
151
                        dec->buffer = NULL;
 
152
                }
 
153
                sbc_init(&dec->sbc, 0);
 
154
                dec->outcaps = NULL;
 
155
                break;
 
156
 
 
157
        case GST_STATE_CHANGE_PAUSED_TO_READY:
 
158
                GST_DEBUG("Finish subband codec");
 
159
                if (dec->buffer) {
 
160
                        gst_buffer_unref(dec->buffer);
 
161
                        dec->buffer = NULL;
 
162
                }
 
163
                sbc_finish(&dec->sbc);
 
164
                if (dec->outcaps) {
 
165
                        gst_caps_unref(dec->outcaps);
 
166
                        dec->outcaps = NULL;
 
167
                }
 
168
                break;
 
169
 
 
170
        default:
 
171
                break;
 
172
        }
 
173
 
 
174
        return parent_class->change_state(element, transition);
 
175
}
 
176
 
 
177
static void gst_sbc_dec_base_init(gpointer g_class)
 
178
{
 
179
        GstElementClass *element_class = GST_ELEMENT_CLASS(g_class);
 
180
 
 
181
        gst_element_class_add_pad_template(element_class,
 
182
                gst_static_pad_template_get(&sbc_dec_sink_factory));
 
183
 
 
184
        gst_element_class_add_pad_template(element_class,
 
185
                gst_static_pad_template_get(&sbc_dec_src_factory));
 
186
 
 
187
        gst_element_class_set_details(element_class, &sbc_dec_details);
 
188
}
 
189
 
 
190
static void gst_sbc_dec_class_init(GstSbcDecClass *klass)
 
191
{
 
192
        GstElementClass *element_class = GST_ELEMENT_CLASS(klass);
 
193
 
 
194
        parent_class = g_type_class_peek_parent(klass);
 
195
 
 
196
        element_class->change_state = GST_DEBUG_FUNCPTR(sbc_dec_change_state);
 
197
 
 
198
        GST_DEBUG_CATEGORY_INIT(sbc_dec_debug, "sbcdec", 0,
 
199
                                                "SBC decoding element");
 
200
}
 
201
 
 
202
static void gst_sbc_dec_init(GstSbcDec *self, GstSbcDecClass *klass)
 
203
{
 
204
        self->sinkpad = gst_pad_new_from_static_template(
 
205
                        &sbc_dec_sink_factory, "sink");
 
206
        gst_pad_set_chain_function(self->sinkpad, GST_DEBUG_FUNCPTR(
 
207
                        sbc_dec_chain));
 
208
        gst_element_add_pad(GST_ELEMENT(self), self->sinkpad);
 
209
 
 
210
        self->srcpad = gst_pad_new_from_static_template(
 
211
                        &sbc_dec_src_factory, "src");
 
212
        gst_element_add_pad(GST_ELEMENT(self), self->srcpad);
 
213
 
 
214
        self->outcaps = NULL;
 
215
}
 
216
 
 
217
gboolean gst_sbc_dec_plugin_init(GstPlugin *plugin)
 
218
{
 
219
        return gst_element_register(plugin, "sbcdec", GST_RANK_PRIMARY,
 
220
                                                        GST_TYPE_SBC_DEC);
 
221
}