ports/www/qt5-webengine/files/sndio_output.cc
Kai Knoblich 21980ea6a9 www/qt5-webengine: Update to 5.12.1
It was again a long journey to bring the port in sync with the other Qt5
ports. It runs now under the hood with Chromium 69.0.3497.128 and applied
security fixes up to version 71.0.3578.94.

Also the approach with the handling of the BUILD.gn files has changed. With
the previous version of www/qt5-webengine (and www/chromium up to r449991) the
boolean variables "is_bsd" and "is_posix" were set to true in BUILDCONFIG
when FreeBSD was detected as operating system during the build process.

Now the boolean variable "is_linux" is set to true as well and this reduces
some patching of BUILD.gn files. It makes it (hopefully) also somewhat easier
to exclude Linux-only features from future www/qt5-webengine versions.

The .debug entries in the pkg-plist are prefixed with @comment each as a
temporary workaround because building with "separate_debug_info" fails to
build QtWebEngineProcess at the moment. (see also: QTBUG-74312)

Many kudos must go to the FreeBSD Chromium team for their ongoing efforts to
keep the browser in a good shape. I was able to use a decent amount of
patches from there which sped up the whole process.

At last but not least: Many thanks must also go to rakuco@ for finding the
last pieces to make www/qt5-webengine more usable and tcberner@ for the moral
support during the whole time.

Changelogs:

https://code.qt.io/cgit/qt/qtwebengine.git/tree/dist/changes-5.12.0
https://code.qt.io/cgit/qt/qtwebengine.git/tree/dist/changes-5.12.1

PR:		234470 [1] (related), 235075 [2]
Reported by:	Michael Danilov [2], aeuii@posteo.de [1]
Reviewed by:	rakuco, tcberner (mentor)
Approved by:	rakuco, tcberner (mentor), kde (maintainer)
Differential Revision:	https://reviews.freebsd.org/D18757
2019-03-27 22:34:04 +00:00

179 lines
4.9 KiB
C++

// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/logging.h"
#include "base/time/time.h"
#include "base/time/default_tick_clock.h"
#include "media/audio/audio_manager_base.h"
#include "media/base/audio_timestamp_helper.h"
#include "media/audio/sndio/sndio_output.h"
namespace media {
static const SampleFormat kSampleFormat = kSampleFormatS16;
void sndio_onmove(void *arg, int delta) {
SndioAudioOutputStream* self = static_cast<SndioAudioOutputStream*>(arg);
self->hw_delay = delta;
}
void sndio_onvol(void *arg, unsigned int vol) {
SndioAudioOutputStream* self = static_cast<SndioAudioOutputStream*>(arg);
self->vol = vol;
}
void *sndio_threadstart(void *arg) {
SndioAudioOutputStream* self = static_cast<SndioAudioOutputStream*>(arg);
self->RealTimeThread();
return NULL;
}
SndioAudioOutputStream::SndioAudioOutputStream(const AudioParameters& params,
AudioManagerBase* manager)
: manager(manager),
params(params),
audio_bus(AudioBus::Create(params)),
bytes_per_frame(params.GetBytesPerFrame(kSampleFormat)),
state(kClosed),
mutex(PTHREAD_MUTEX_INITIALIZER) {
}
SndioAudioOutputStream::~SndioAudioOutputStream() {
if (state != kClosed)
Close();
}
bool SndioAudioOutputStream::Open() {
struct sio_par par;
int sig;
if (params.format() != AudioParameters::AUDIO_PCM_LINEAR &&
params.format() != AudioParameters::AUDIO_PCM_LOW_LATENCY) {
LOG(WARNING) << "Unsupported audio format.";
return false;
}
sio_initpar(&par);
par.rate = params.sample_rate();
par.pchan = params.channels();
par.bits = SampleFormatToBitsPerChannel(kSampleFormat);
par.bps = par.bits / 8;
par.sig = sig = par.bits != 8 ? 1 : 0;
par.le = SIO_LE_NATIVE;
par.appbufsz = params.frames_per_buffer();
hdl = sio_open(SIO_DEVANY, SIO_PLAY, 0);
if (hdl == NULL) {
LOG(ERROR) << "Couldn't open audio device.";
return false;
}
if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par)) {
LOG(ERROR) << "Couldn't set audio parameters.";
goto bad_close;
}
if (par.rate != (unsigned int)params.sample_rate() ||
par.pchan != (unsigned int)params.channels() ||
par.bits != (unsigned int)SampleFormatToBitsPerChannel(kSampleFormat) ||
par.sig != (unsigned int)sig ||
(par.bps > 1 && par.le != SIO_LE_NATIVE) ||
(par.bits != par.bps * 8)) {
LOG(ERROR) << "Unsupported audio parameters.";
goto bad_close;
}
state = kStopped;
volpending = 0;
vol = 0;
buffer = new char[audio_bus->frames() * params.GetBytesPerFrame(kSampleFormat)];
sio_onmove(hdl, sndio_onmove, this);
sio_onvol(hdl, sndio_onvol, this);
return true;
bad_close:
sio_close(hdl);
return false;
}
void SndioAudioOutputStream::Close() {
if (state == kClosed)
return;
if (state == kRunning)
Stop();
state = kClosed;
delete [] buffer;
sio_close(hdl);
manager->ReleaseOutputStream(this); // Calls the destructor
}
void SndioAudioOutputStream::Start(AudioSourceCallback* callback) {
state = kRunning;
hw_delay = 0;
source = callback;
sio_start(hdl);
if (pthread_create(&thread, NULL, sndio_threadstart, this) != 0) {
LOG(ERROR) << "Failed to create real-time thread.";
sio_stop(hdl);
state = kStopped;
}
}
void SndioAudioOutputStream::Stop() {
if (state == kStopped)
return;
state = kStopWait;
pthread_join(thread, NULL);
sio_stop(hdl);
state = kStopped;
}
void SndioAudioOutputStream::SetVolume(double v) {
pthread_mutex_lock(&mutex);
vol = v * SIO_MAXVOL;
volpending = 1;
pthread_mutex_unlock(&mutex);
}
void SndioAudioOutputStream::GetVolume(double* v) {
pthread_mutex_lock(&mutex);
*v = vol * (1. / SIO_MAXVOL);
pthread_mutex_unlock(&mutex);
}
void SndioAudioOutputStream::RealTimeThread(void) {
int avail, count;
while (state == kRunning) {
// Update volume if needed
pthread_mutex_lock(&mutex);
if (volpending) {
volpending = 0;
sio_setvol(hdl, vol);
}
pthread_mutex_unlock(&mutex);
// Get data to play
const base::TimeDelta delay = AudioTimestampHelper::FramesToTime(hw_delay, params.sample_rate() * 1000);
count = source->OnMoreData(delay, base::TimeTicks::Now(), 0, audio_bus.get());
audio_bus->ToInterleaved(count, SampleFormatToBytesPerChannel(kSampleFormat), buffer);
if (count == 0) {
// We have to submit something to the device
count = audio_bus->frames();
memset(buffer, 0, count * params.GetBytesPerFrame(kSampleFormat));
LOG(WARNING) << "No data to play, running empty cycle.";
}
// Submit data to the device
avail = count * params.GetBytesPerFrame(kSampleFormat);
count = sio_write(hdl, buffer, avail);
if (count == 0) {
LOG(WARNING) << "Audio device disconnected.";
break;
}
// Update hardware pointer
hw_delay += count;
}
}
} // namespace media