1/*
2 * Copyright (C) 2017 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "LibWebRTCAudioModule.h"
28
29#if USE(LIBWEBRTC)
30
31#include <wtf/MonotonicTime.h>
32
33namespace WebCore {
34
35LibWebRTCAudioModule::LibWebRTCAudioModule()
36 : m_audioTaskRunner(rtc::Thread::Create())
37{
38 m_audioTaskRunner->SetName("WebKitWebRTCAudioModule", nullptr);
39 m_audioTaskRunner->Start();
40}
41
42int32_t LibWebRTCAudioModule::RegisterAudioCallback(webrtc::AudioTransport* audioTransport)
43{
44 m_audioTransport = audioTransport;
45 return 0;
46}
47
48void LibWebRTCAudioModule::OnMessage(rtc::Message* message)
49{
50 ASSERT_UNUSED(message, message->message_id == 1);
51 StartPlayoutOnAudioThread();
52}
53
54int32_t LibWebRTCAudioModule::StartPlayout()
55{
56 if (!m_isPlaying && m_audioTaskRunner) {
57 m_audioTaskRunner->Post(RTC_FROM_HERE, this, 1);
58 m_isPlaying = true;
59 }
60 return 0;
61}
62
63int32_t LibWebRTCAudioModule::StopPlayout()
64{
65 if (m_isPlaying)
66 m_isPlaying = false;
67 return 0;
68}
69
70// libwebrtc uses 10ms frames.
71const unsigned samplingRate = 48000;
72const unsigned frameLengthMs = 10;
73const unsigned samplesPerFrame = samplingRate * frameLengthMs / 1000;
74const unsigned pollSamples = 5;
75const unsigned pollInterval = 5 * frameLengthMs;
76const unsigned channels = 2;
77const unsigned bytesPerSample = 2;
78
79void LibWebRTCAudioModule::StartPlayoutOnAudioThread()
80{
81 MonotonicTime startTime = MonotonicTime::now();
82 while (true) {
83 PollFromSource();
84
85 MonotonicTime now = MonotonicTime::now();
86 double sleepFor = pollInterval - remainder((now - startTime).milliseconds(), pollInterval);
87 m_audioTaskRunner->SleepMs(sleepFor);
88 if (!m_isPlaying)
89 return;
90 }
91}
92
93void LibWebRTCAudioModule::PollFromSource()
94{
95 if (!m_audioTransport)
96 return;
97
98 for (unsigned i = 0; i < pollSamples; i++) {
99 int64_t elapsedTime = -1;
100 int64_t ntpTime = -1;
101 char data[(bytesPerSample * channels * samplesPerFrame)];
102 m_audioTransport->PullRenderData(bytesPerSample * 8, samplingRate, channels, samplesPerFrame, data, &elapsedTime, &ntpTime);
103 }
104}
105
106} // namespace WebCore
107
108#endif // USE(LIBWEBRTC)
109