source: trunk/src/3rdparty/phonon/gstreamer/audiodataoutput.cpp

Last change on this file was 846, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 4.9 KB
Line 
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>
4
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.
13
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.
18
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/>.
21
22*/
23
24#include "audiodataoutput.h"
25#include "gsthelper.h"
26#include "medianode.h"
27#include "mediaobject.h"
28#include <QtCore/QVector>
29#include <QtCore/QMap>
30#include <phonon/audiooutput.h>
31
32QT_BEGIN_HEADER
33QT_BEGIN_NAMESPACE
34
35namespace Phonon
36{
37namespace Gstreamer
38{
39AudioDataOutput::AudioDataOutput(Backend *backend, QObject *parent)
40 : QObject(parent),
41 MediaNode(backend, AudioSink | AudioSource)
42{
43 static int count = 0;
44 m_name = "AudioDataOutput" + QString::number(count++);
45
46 m_queue = gst_element_factory_make ("identity", NULL);
47 gst_object_ref(m_queue);
48 m_isValid = true;
49}
50
51AudioDataOutput::~AudioDataOutput()
52{
53 gst_element_set_state(m_queue, GST_STATE_NULL);
54 gst_object_unref(m_queue);
55}
56
57int AudioDataOutput::dataSize() const
58{
59 return m_dataSize;
60}
61
62int AudioDataOutput::sampleRate() const
63{
64 return 44100;
65}
66
67void AudioDataOutput::setDataSize(int size)
68{
69 m_dataSize = size;
70}
71
72typedef QMap<Phonon::AudioDataOutput::Channel, QVector<float> > FloatMap;
73typedef QMap<Phonon::AudioDataOutput::Channel, QVector<qint16> > IntMap;
74
75inline void AudioDataOutput::convertAndEmit(const QVector<qint16> &leftBuffer, const QVector<qint16> &rightBuffer)
76{
77 //TODO: Floats
78 IntMap map;
79 map.insert(Phonon::AudioDataOutput::LeftChannel, leftBuffer);
80 map.insert(Phonon::AudioDataOutput::RightChannel, rightBuffer);
81 emit dataReady(map);
82}
83
84void AudioDataOutput::processBuffer(GstPad*, GstBuffer* buffer, gpointer gThat)
85{
86 // TODO emit endOfMedia
87 AudioDataOutput *that = reinterpret_cast<AudioDataOutput*>(gThat);
88
89 // determine the number of channels
90 GstStructure* structure = gst_caps_get_structure (GST_BUFFER_CAPS(buffer), 0);
91 gst_structure_get_int (structure, "channels", &that->m_channels);
92
93 if (that->m_channels > 2 || that->m_channels < 0) {
94 qWarning() << Q_FUNC_INFO << ": Number of channels not supported: " << that->m_channels;
95 return;
96 }
97
98 gint16 *data = reinterpret_cast<gint16*>(GST_BUFFER_DATA(buffer));
99 guint size = GST_BUFFER_SIZE(buffer) / sizeof(gint16);
100
101 that->m_pendingData.reserve(that->m_pendingData.size() + size);
102
103 for (uint i=0; i<size; i++) {
104 // 8 bit? interleaved? yay for lacking documentation!
105 that->m_pendingData.append(data[i]);
106 }
107
108 while (that->m_pendingData.size() > that->m_dataSize * that->m_channels) {
109 if (that->m_channels == 1) {
110 QVector<qint16> intBuffer(that->m_dataSize);
111 memcpy(intBuffer.data(), that->m_pendingData.constData(), that->m_dataSize * sizeof(qint16));
112
113 that->convertAndEmit(intBuffer, intBuffer);
114 int newSize = that->m_pendingData.size() - that->m_dataSize;
115 memmove(that->m_pendingData.data(), that->m_pendingData.constData() + that->m_dataSize, newSize * sizeof(qint16));
116 that->m_pendingData.resize(newSize);
117 } else {
118 QVector<qint16> left(that->m_dataSize), right(that->m_dataSize);
119 for (int i=0; i<that->m_dataSize; i++) {
120 left[i] = that->m_pendingData[i*2];
121 right[i] = that->m_pendingData[i*2+1];
122 }
123 that->m_pendingData.resize(that->m_pendingData.size() - that->m_dataSize*2);
124 that->convertAndEmit(left, right);
125 }
126 }
127}
128
129void AudioDataOutput::mediaNodeEvent(const MediaNodeEvent *event)
130{
131 if (event->type() == MediaNodeEvent::MediaObjectConnected && root()) {
132 g_object_set(G_OBJECT(audioElement()), "sync", true, (const char*)NULL);
133 GstPad *audiopad = gst_element_get_pad (audioElement(), "src");
134 gst_pad_add_buffer_probe (audiopad, G_CALLBACK(processBuffer), this);
135 gst_object_unref (audiopad);
136 return;
137 }
138
139 MediaNode::mediaNodeEvent(event);
140}
141
142}} //namespace Phonon::Gstreamer
143
144QT_END_NAMESPACE
145QT_END_HEADER
146
147#include "moc_audiodataoutput.cpp"
148// vim: sw=4 ts=4
149
Note: See TracBrowser for help on using the repository browser.