1
/* This file is part of the KDE project
2
Copyright (C) 2006 Matthias Kretz <kretz@kde.org>
3
Copyright (C) 2009 Martin Sandsmark <sandsmark@samfundet.no>
5
This library is free software; you can redistribute it and/or
6
modify it under the terms of the GNU Lesser General Public
7
License as published by the Free Software Foundation; either
8
version 2.1 of the License, or (at your option) version 3, or any
9
later version accepted by the membership of KDE e.V. (or its
10
successor approved by the membership of KDE e.V.), Nokia Corporation
11
(or its successors, if any) and the KDE Free Qt Foundation, which shall
12
act as a proxy defined in Section 6 of version 3 of the license.
14
This library is distributed in the hope that it will be useful,
15
but WITHOUT ANY WARRANTY; without even the implied warranty of
16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17
Lesser General Public License for more details.
19
You should have received a copy of the GNU Lesser General Public
20
License along with this library. If not, see <http://www.gnu.org/licenses/>.
24
#include "audiodataoutput.h"
25
#include "gsthelper.h"
26
#include "medianode.h"
27
#include "medianodeevent.h"
28
#include "mediaobject.h"
29
#include <QtCore/QVector>
30
#include <QtCore/QMap>
31
#include <phonon/audiooutput.h>
33
#include <gst/gstutils.h>
42
AudioDataOutput::AudioDataOutput(Backend *backend, QObject *parent)
44
MediaNode(backend, AudioSink | AudioSource)
47
m_name = "AudioDataOutput" + QString::number(count++);
49
m_queue = gst_element_factory_make ("identity", NULL);
50
gst_object_ref(m_queue);
54
AudioDataOutput::~AudioDataOutput()
56
gst_element_set_state(m_queue, GST_STATE_NULL);
57
gst_object_unref(m_queue);
60
int AudioDataOutput::dataSize() const
65
int AudioDataOutput::sampleRate() const
70
void AudioDataOutput::setDataSize(int size)
75
typedef QMap<Phonon::AudioDataOutput::Channel, QVector<float> > FloatMap;
76
typedef QMap<Phonon::AudioDataOutput::Channel, QVector<qint16> > IntMap;
78
inline void AudioDataOutput::convertAndEmit(const QVector<qint16> &leftBuffer, const QVector<qint16> &rightBuffer)
82
map.insert(Phonon::AudioDataOutput::LeftChannel, leftBuffer);
83
map.insert(Phonon::AudioDataOutput::RightChannel, rightBuffer);
87
void AudioDataOutput::processBuffer(GstPad*, GstBuffer* buffer, gpointer gThat)
89
// TODO emit endOfMedia
90
AudioDataOutput *that = reinterpret_cast<AudioDataOutput*>(gThat);
92
// determine the number of channels
93
GstStructure* structure = gst_caps_get_structure (GST_BUFFER_CAPS(buffer), 0);
94
gst_structure_get_int (structure, "channels", &that->m_channels);
96
if (that->m_channels > 2 || that->m_channels < 0) {
97
qWarning() << Q_FUNC_INFO << ": Number of channels not supported: " << that->m_channels;
101
gint16 *data = reinterpret_cast<gint16*>(GST_BUFFER_DATA(buffer));
102
guint size = GST_BUFFER_SIZE(buffer) / sizeof(gint16);
104
that->m_pendingData.reserve(that->m_pendingData.size() + size);
106
for (uint i=0; i<size; i++) {
107
// 8 bit? interleaved? yay for lacking documentation!
108
that->m_pendingData.append(data[i]);
111
while (that->m_pendingData.size() > that->m_dataSize * that->m_channels) {
112
if (that->m_channels == 1) {
113
QVector<qint16> intBuffer(that->m_dataSize);
114
memcpy(intBuffer.data(), that->m_pendingData.constData(), that->m_dataSize * sizeof(qint16));
116
that->convertAndEmit(intBuffer, intBuffer);
117
int newSize = that->m_pendingData.size() - that->m_dataSize;
118
memmove(that->m_pendingData.data(), that->m_pendingData.constData() + that->m_dataSize, newSize * sizeof(qint16));
119
that->m_pendingData.resize(newSize);
121
QVector<qint16> left(that->m_dataSize), right(that->m_dataSize);
122
for (int i=0; i<that->m_dataSize; i++) {
123
left[i] = that->m_pendingData[i*2];
124
right[i] = that->m_pendingData[i*2+1];
126
that->m_pendingData.resize(that->m_pendingData.size() - that->m_dataSize*2);
127
that->convertAndEmit(left, right);
132
void AudioDataOutput::mediaNodeEvent(const MediaNodeEvent *event)
134
if (event->type() == MediaNodeEvent::MediaObjectConnected && root()) {
135
g_object_set(G_OBJECT(audioElement()), "sync", true, (const char*)NULL);
136
GstPad *audiopad = gst_element_get_pad (audioElement(), "src");
137
gst_pad_add_buffer_probe (audiopad, G_CALLBACK(processBuffer), this);
138
gst_object_unref (audiopad);
142
MediaNode::mediaNodeEvent(event);
145
}} //namespace Phonon::Gstreamer
150
#include "moc_audiodataoutput.cpp"