[WPE][GTK] Bump minimum versions of GLib, GTK, libsoup, ATK, GStreamer, and Cairo
[WebKit-https.git] / Source / WebCore / platform / mediastream / gstreamer / RealtimeOutgoingAudioSourceLibWebRTC.cpp
1 /*
2  * Copyright (C) 2017 Igalia S.L
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * aint with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 #include "config.h"
21
22 #if USE(LIBWEBRTC) && USE(GSTREAMER)
23 #include "RealtimeOutgoingAudioSourceLibWebRTC.h"
24
25 #include "LibWebRTCAudioFormat.h"
26 #include "LibWebRTCProvider.h"
27 #include "NotImplemented.h"
28 #include "gstreamer/GStreamerAudioData.h"
29
30 namespace WebCore {
31
32 RealtimeOutgoingAudioSourceLibWebRTC::RealtimeOutgoingAudioSourceLibWebRTC(Ref<MediaStreamTrackPrivate>&& audioSource)
33     : RealtimeOutgoingAudioSource(WTFMove(audioSource))
34 {
35     m_adapter = adoptGRef(gst_adapter_new()),
36     m_sampleConverter = nullptr;
37 }
38
39 RealtimeOutgoingAudioSourceLibWebRTC::~RealtimeOutgoingAudioSourceLibWebRTC()
40 {
41     unobserveSource();
42     m_sampleConverter = nullptr;
43 }
44
45 Ref<RealtimeOutgoingAudioSource> RealtimeOutgoingAudioSource::create(Ref<MediaStreamTrackPrivate>&& audioSource)
46 {
47     return RealtimeOutgoingAudioSourceLibWebRTC::create(WTFMove(audioSource));
48 }
49
50 static inline std::unique_ptr<GStreamerAudioStreamDescription> libwebrtcAudioFormat(int sampleRate,
51     size_t channelCount)
52 {
53     GstAudioFormat format = gst_audio_format_build_integer(
54         LibWebRTCAudioFormat::isSigned,
55         LibWebRTCAudioFormat::isBigEndian ? G_BIG_ENDIAN : G_LITTLE_ENDIAN,
56         LibWebRTCAudioFormat::sampleSize,
57         LibWebRTCAudioFormat::sampleSize);
58
59     GstAudioInfo info;
60
61     size_t libWebRTCChannelCount = channelCount >= 2 ? 2 : channelCount;
62     gst_audio_info_set_format(&info, format, sampleRate, libWebRTCChannelCount, nullptr);
63
64     return std::unique_ptr<GStreamerAudioStreamDescription>(new GStreamerAudioStreamDescription(info));
65 }
66
67 void RealtimeOutgoingAudioSourceLibWebRTC::audioSamplesAvailable(const MediaTime&,
68     const PlatformAudioData& audioData, const AudioStreamDescription& streamDescription,
69     size_t /* sampleCount */)
70 {
71     auto data = static_cast<const GStreamerAudioData&>(audioData);
72     auto desc = static_cast<const GStreamerAudioStreamDescription&>(streamDescription);
73
74     if (m_sampleConverter && !gst_audio_info_is_equal(m_inputStreamDescription->getInfo(), desc.getInfo())) {
75         GST_ERROR_OBJECT(this, "FIXME - Audio format renegotiation is not possible yet!");
76         m_sampleConverter = nullptr;
77     }
78
79     if (!m_sampleConverter) {
80         m_inputStreamDescription = std::unique_ptr<GStreamerAudioStreamDescription>(new GStreamerAudioStreamDescription(desc.getInfo()));
81         m_outputStreamDescription = libwebrtcAudioFormat(LibWebRTCAudioFormat::sampleRate, streamDescription.numberOfChannels());
82         m_sampleConverter.reset(gst_audio_converter_new(GST_AUDIO_CONVERTER_FLAG_IN_WRITABLE,
83             m_inputStreamDescription->getInfo(),
84             m_outputStreamDescription->getInfo(),
85             nullptr));
86     }
87
88     LockHolder locker(m_adapterMutex);
89     auto buffer = gst_sample_get_buffer(data.getSample());
90     gst_adapter_push(m_adapter.get(), gst_buffer_ref(buffer));
91     LibWebRTCProvider::callOnWebRTCSignalingThread([protectedThis = makeRef(*this)] {
92         protectedThis->pullAudioData();
93     });
94 }
95
96 void RealtimeOutgoingAudioSourceLibWebRTC::pullAudioData()
97 {
98     if (!m_inputStreamDescription || !m_outputStreamDescription) {
99         GST_INFO("No stream description set yet.");
100
101         return;
102     }
103
104     size_t outChunkSampleCount = LibWebRTCAudioFormat::chunkSampleCount;
105     size_t outBufferSize = outChunkSampleCount * m_outputStreamDescription->getInfo()->bpf;
106
107     LockHolder locker(m_adapterMutex);
108     size_t inChunkSampleCount = gst_audio_converter_get_in_frames(m_sampleConverter.get(), outChunkSampleCount);
109     size_t inBufferSize = inChunkSampleCount * m_inputStreamDescription->getInfo()->bpf;
110
111     while (gst_adapter_available(m_adapter.get()) > inBufferSize) {
112         auto inBuffer = adoptGRef(gst_adapter_take_buffer(m_adapter.get(), inBufferSize));
113         m_audioBuffer.grow(outBufferSize);
114         if (isSilenced())
115             gst_audio_format_fill_silence(m_outputStreamDescription->getInfo()->finfo, m_audioBuffer.data(), outBufferSize);
116         else {
117             auto inMap = GstMappedBuffer::create(inBuffer.get(), GST_MAP_READ);
118
119             gpointer in[1] = { inMap->data() };
120             gpointer out[1] = { m_audioBuffer.data() };
121             if (!gst_audio_converter_samples(m_sampleConverter.get(), static_cast<GstAudioConverterFlags>(0), in, inChunkSampleCount, out, outChunkSampleCount)) {
122                 GST_ERROR("Could not convert samples.");
123
124                 return;
125             }
126         }
127
128         sendAudioFrames(m_audioBuffer.data(), LibWebRTCAudioFormat::sampleSize, static_cast<int>(m_outputStreamDescription->sampleRate()),
129             static_cast<int>(m_outputStreamDescription->numberOfChannels()), outChunkSampleCount);
130     }
131 }
132
133 bool RealtimeOutgoingAudioSourceLibWebRTC::isReachingBufferedAudioDataHighLimit()
134 {
135     notImplemented();
136     return false;
137 }
138
139 bool RealtimeOutgoingAudioSourceLibWebRTC::isReachingBufferedAudioDataLowLimit()
140 {
141     notImplemented();
142     return false;
143 }
144
145 bool RealtimeOutgoingAudioSourceLibWebRTC::hasBufferedEnoughData()
146 {
147     notImplemented();
148     return false;
149 }
150
151 } // namespace WebCore
152
153 #endif // USE(LIBWEBRTC)