various: moved more to core lib

This commit is contained in:
itsmattkc
2023-01-19 16:01:31 -08:00
parent dd9c52ab59
commit c1c6893713
92 changed files with 448 additions and 1558 deletions
-2
View File
@@ -33,7 +33,5 @@ set(OLIVE_SOURCES
codec/frame.h
codec/planarfiledevice.cpp
codec/planarfiledevice.h
codec/samplebuffer.cpp
codec/samplebuffer.h
PARENT_SCOPE
)
-1
View File
@@ -31,7 +31,6 @@ extern "C" {
#include <QWaitCondition>
#include <stdint.h>
#include "codec/samplebuffer.h"
#include "node/block/block.h"
#include "node/project/footage/footagedescription.h"
#include "render/cancelatom.h"
+4 -4
View File
@@ -257,7 +257,7 @@ void EncodingParams::Save(QXmlStreamWriter *writer) const
writer->writeTextElement(QStringLiteral("codec"), QString::number(audio_codec_));
writer->writeTextElement(QStringLiteral("samplerate"), QString::number(audio_params_.sample_rate()));
writer->writeTextElement(QStringLiteral("channellayout"), QString::number(audio_params_.channel_layout()));
writer->writeTextElement(QStringLiteral("format"), QString::number(audio_params_.format()));
writer->writeTextElement(QStringLiteral("format"), QString::fromStdString(audio_params_.format().to_string()));
writer->writeTextElement(QStringLiteral("bitrate"), QString::number(audio_bit_rate_));
}
@@ -337,9 +337,9 @@ QStringList Encoder::GetPixelFormatsForCodec(ExportCodec::Codec c) const
return QStringList();
}
std::vector<AudioParams::Format> Encoder::GetSampleFormatsForCodec(ExportCodec::Codec c) const
std::vector<SampleFormat> Encoder::GetSampleFormatsForCodec(ExportCodec::Codec c) const
{
return std::vector<AudioParams::Format>();
return std::vector<SampleFormat>();
}
QMatrix4x4 EncodingParams::GenerateMatrix(EncodingParams::VideoScalingMethod method,
@@ -471,7 +471,7 @@ bool EncodingParams::LoadV1(QXmlStreamReader *reader)
} else if (reader->name() == QStringLiteral("channellayout")) {
audio_params_.set_channel_layout(reader->readElementText().toULongLong());
} else if (reader->name() == QStringLiteral("format")) {
audio_params_.set_format(static_cast<AudioParams::Format>(reader->readElementText().toInt()));
audio_params_.set_format(SampleFormat::from_string(reader->readElementText().toStdString()));
} else if (reader->name() == QStringLiteral("bitrate")) {
audio_bit_rate_ = reader->readElementText().toLongLong();
} else {
+1 -3
View File
@@ -29,9 +29,7 @@
#include "codec/exportcodec.h"
#include "codec/exportformat.h"
#include "codec/frame.h"
#include "codec/samplebuffer.h"
#include "node/block/subtitle/subtitle.h"
#include "render/audioparams.h"
#include "render/colortransform.h"
#include "render/subtitleparams.h"
#include "render/videoparams.h"
@@ -204,7 +202,7 @@ public:
static Encoder *CreateFromParams(const EncodingParams &params);
virtual QStringList GetPixelFormatsForCodec(ExportCodec::Codec c) const;
virtual std::vector<AudioParams::Format> GetSampleFormatsForCodec(ExportCodec::Codec c) const;
virtual std::vector<SampleFormat> GetSampleFormatsForCodec(ExportCodec::Codec c) const;
const EncodingParams& params() const;
+2 -2
View File
@@ -218,9 +218,9 @@ QStringList ExportFormat::GetPixelFormatsForCodec(ExportFormat::Format f, Export
return list;
}
std::vector<AudioParams::Format> ExportFormat::GetSampleFormatsForCodec(Format format, ExportCodec::Codec c)
std::vector<SampleFormat> ExportFormat::GetSampleFormatsForCodec(Format format, ExportCodec::Codec c)
{
std::vector<AudioParams::Format> f;
std::vector<SampleFormat> f;
Encoder *e = Encoder::CreateFromFormat(format, EncodingParams());
if (e) {
+1 -2
View File
@@ -26,7 +26,6 @@
#include "common/define.h"
#include "exportcodec.h"
#include "render/audioparams.h"
namespace olive {
@@ -62,7 +61,7 @@ public:
static QList<ExportCodec::Codec> GetSubtitleCodecs(ExportFormat::Format f);
static QStringList GetPixelFormatsForCodec(Format f, ExportCodec::Codec c);
static std::vector<AudioParams::Format> GetSampleFormatsForCodec(Format f, ExportCodec::Codec c);
static std::vector<SampleFormat> GetSampleFormatsForCodec(Format f, ExportCodec::Codec c);
};
+1 -1
View File
@@ -468,7 +468,7 @@ FootageDescription FFmpegDecoder::Probe(const QString &filename, CancelAtom *can
stream.set_stream_index(i);
stream.set_channel_layout(channel_layout);
stream.set_sample_rate(avstream->codecpar->sample_rate);
stream.set_format(AudioParams::kInternalFormat);
stream.set_format(FFmpegUtils::GetNativeSampleFormat(static_cast<AVSampleFormat>(avstream->codecpar->format)));
stream.set_time_base(avstream->time_base);
stream.set_duration(avstream->duration);
desc.AddAudioStream(stream);
+28 -28
View File
@@ -52,7 +52,7 @@ QStringList FFmpegEncoder::GetPixelFormatsForCodec(ExportCodec::Codec c) const
{
QStringList pix_fmts;
const AVCodec* codec_info = GetEncoder(c, AudioParams::kFormatInvalid);
const AVCodec* codec_info = GetEncoder(c, SampleFormat::INVALID);
if (codec_info) {
for (int i=0; codec_info->pix_fmts[i]!=-1; i++) {
@@ -69,29 +69,29 @@ QStringList FFmpegEncoder::GetPixelFormatsForCodec(ExportCodec::Codec c) const
return pix_fmts;
}
std::vector<AudioParams::Format> FFmpegEncoder::GetSampleFormatsForCodec(ExportCodec::Codec c) const
std::vector<SampleFormat> FFmpegEncoder::GetSampleFormatsForCodec(ExportCodec::Codec c) const
{
std::vector<AudioParams::Format> f;
std::vector<SampleFormat> f;
if (c == ExportCodec::kCodecPCM) {
// FFmpeg lists these as separate codecs so we need custom functionality here
// We list signed 16 first because ExportDialog will always use the first element by default
// (because first element is the "default" in FFmpeg)
// (because first element is the "default" in tFFmpeg)
f = {
AudioParams::kFormatSigned16Packed,
AudioParams::kFormatUnsigned8Packed,
AudioParams::kFormatSigned32Packed,
AudioParams::kFormatSigned64Packed,
AudioParams::kFormatFloat32Packed,
AudioParams::kFormatFloat64Packed
SampleFormat::S16,
SampleFormat::U8,
SampleFormat::S32,
SampleFormat::S64,
SampleFormat::F32,
SampleFormat::F64
};
} else {
const AVCodec* codec_info = GetEncoder(c, AudioParams::kFormatInvalid);
const AVCodec* codec_info = GetEncoder(c, SampleFormat::INVALID);
if (codec_info && codec_info->sample_fmts) {
for (int i=0; codec_info->sample_fmts[i]!=-1; i++) {
AudioParams::Format this_format = FFmpegUtils::GetNativeSampleFormat(static_cast<AVSampleFormat>(codec_info->sample_fmts[i]));
if (this_format != AudioParams::kFormatInvalid) {
SampleFormat this_format = FFmpegUtils::GetNativeSampleFormat(static_cast<AVSampleFormat>(codec_info->sample_fmts[i]));
if (this_format != SampleFormat::INVALID) {
f.push_back(this_format);
}
}
@@ -881,7 +881,7 @@ bool FFmpegEncoder::InitializeResampleContext(const AudioParams &audio)
return true;
}
const AVCodec *FFmpegEncoder::GetEncoder(ExportCodec::Codec c, AudioParams::Format aformat)
const AVCodec *FFmpegEncoder::GetEncoder(ExportCodec::Codec c, SampleFormat aformat)
{
switch (c) {
case ExportCodec::kCodecH264:
@@ -912,26 +912,26 @@ const AVCodec *FFmpegEncoder::GetEncoder(ExportCodec::Codec c, AudioParams::Form
return avcodec_find_encoder(AV_CODEC_ID_AAC);
case ExportCodec::kCodecPCM:
switch (aformat) {
case AudioParams::kFormatInvalid:
case AudioParams::kFormatCount:
case AudioParams::kFormatUnsigned8Planar:
case AudioParams::kFormatSigned16Planar:
case AudioParams::kFormatSigned32Planar:
case AudioParams::kFormatSigned64Planar:
case AudioParams::kFormatFloat32Planar:
case AudioParams::kFormatFloat64Planar:
case SampleFormat::INVALID:
case SampleFormat::COUNT:
case SampleFormat::U8P:
case SampleFormat::S16P:
case SampleFormat::S32P:
case SampleFormat::S64P:
case SampleFormat::F32P:
case SampleFormat::F64P:
break;
case AudioParams::kFormatUnsigned8Packed:
case SampleFormat::U8:
return avcodec_find_encoder(AV_CODEC_ID_PCM_U8);
case AudioParams::kFormatSigned16Packed:
case SampleFormat::S16:
return avcodec_find_encoder(AV_CODEC_ID_PCM_S16LE);
case AudioParams::kFormatSigned32Packed:
case SampleFormat::S32:
return avcodec_find_encoder(AV_CODEC_ID_PCM_S32LE);
case AudioParams::kFormatSigned64Packed:
case SampleFormat::S64:
return avcodec_find_encoder(AV_CODEC_ID_PCM_S64LE);
case AudioParams::kFormatFloat32Packed:
case SampleFormat::F32:
return avcodec_find_encoder(AV_CODEC_ID_PCM_F32LE);
case AudioParams::kFormatFloat64Packed:
case SampleFormat::F64:
return avcodec_find_encoder(AV_CODEC_ID_PCM_F64LE);
}
break;
+2 -2
View File
@@ -41,7 +41,7 @@ public:
virtual QStringList GetPixelFormatsForCodec(ExportCodec::Codec c) const override;
virtual std::vector<AudioParams::Format> GetSampleFormatsForCodec(ExportCodec::Codec c) const override;
virtual std::vector<SampleFormat> GetSampleFormatsForCodec(ExportCodec::Codec c) const override;
virtual bool Open() override;
@@ -82,7 +82,7 @@ private:
bool InitializeResampleContext(const AudioParams &audio);
static const AVCodec *GetEncoder(ExportCodec::Codec c, AudioParams::Format aformat);
static const AVCodec *GetEncoder(ExportCodec::Codec c, SampleFormat aformat);
AVFormatContext* fmt_ctx_;
+3 -3
View File
@@ -21,14 +21,14 @@
#ifndef PLANARFILEDEVICE_H
#define PLANARFILEDEVICE_H
#include <olive/core/core.h>
#include <QFile>
#include <QObject>
#include "codec/samplebuffer.h"
#include "common/define.h"
namespace olive {
using namespace core;
class PlanarFileDevice : public QObject
{
Q_OBJECT
-255
View File
@@ -1,255 +0,0 @@
/***
Olive - Non-Linear Video Editor
Copyright (C) 2022 Olive Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#include "samplebuffer.h"
#include <QDebug>
#include "common/cpuoptimize.h"
namespace olive {
SampleBuffer::SampleBuffer() :
sample_count_per_channel_(0)
{
}
SampleBuffer::SampleBuffer(const AudioParams &audio_params, const rational &length) :
audio_params_(audio_params)
{
sample_count_per_channel_ = audio_params_.time_to_samples(length);
allocate();
}
SampleBuffer::SampleBuffer(const AudioParams &audio_params, size_t samples_per_channel) :
audio_params_(audio_params),
sample_count_per_channel_(samples_per_channel)
{
allocate();
}
const AudioParams &SampleBuffer::audio_params() const
{
return audio_params_;
}
void SampleBuffer::set_audio_params(const AudioParams &params)
{
if (is_allocated()) {
qWarning() << "Tried to set parameters on allocated sample buffer";
return;
}
audio_params_ = params;
}
void SampleBuffer::set_sample_count(const size_t &sample_count)
{
if (is_allocated()) {
qWarning() << "Tried to set sample count on allocated sample buffer";
return;
}
sample_count_per_channel_ = sample_count;
}
void SampleBuffer::allocate()
{
if (!audio_params_.is_valid()) {
qWarning() << "Tried to allocate sample buffer with invalid audio parameters";
return;
}
if (!sample_count_per_channel_) {
qWarning() << "Tried to allocate sample buffer with zero sample count";
return;
}
if (is_allocated()) {
qWarning() << "Tried to allocate already allocated sample buffer";
return;
}
data_.resize(audio_params_.channel_count());
for (int i=0; i<audio_params_.channel_count(); i++) {
data_[i].resize(sample_count_per_channel_);
}
}
void SampleBuffer::destroy()
{
data_.clear();
}
void SampleBuffer::reverse()
{
if (!is_allocated()) {
qWarning() << "Tried to reverse an unallocated sample buffer";
return;
}
size_t half_nb_sample = sample_count_per_channel_ / 2;
for (size_t i=0;i<half_nb_sample;i++) {
size_t opposite_ind = sample_count_per_channel_ - i - 1;
for (int j=0;j<audio_params_.channel_count();j++) {
std::swap(data_[j][i], data_[j][opposite_ind]);
}
}
}
void SampleBuffer::speed(double speed)
{
if (!is_allocated()) {
qWarning() << "Tried to speed an unallocated sample buffer";
return;
}
sample_count_per_channel_ = qRound(static_cast<double>(sample_count_per_channel_) / speed);
std::vector< std::vector<float> > output_data;
output_data.resize(audio_params_.channel_count());
for (int i=0; i<audio_params_.channel_count(); i++) {
output_data[i].resize(sample_count_per_channel_);
}
for (size_t i=0;i<sample_count_per_channel_;i++) {
size_t input_index = qFloor(static_cast<double>(i) * speed);
for (int j=0;j<audio_params_.channel_count();j++) {
output_data[j][i] = data_[j][input_index];
}
}
data_ = output_data;
}
void SampleBuffer::transform_volume(float f)
{
for (int i=0;i<audio_params().channel_count();i++) {
transform_volume_for_channel(i, f);
}
}
void SampleBuffer::transform_volume_for_channel(int channel, float volume)
{
float *cdat = data_[channel].data();
size_t unopt_start = 0;
#if defined(Q_PROCESSOR_X86) || defined(Q_PROCESSOR_ARM)
__m128 mult = _mm_load1_ps(&volume);
unopt_start = (sample_count_per_channel_ / 4) * 4;
for (size_t j=0; j<unopt_start; j+=4) {
float *here = cdat + j;
__m128 samples = _mm_loadu_ps(here);
__m128 multiplied = _mm_mul_ps(samples, mult);
_mm_storeu_ps(here, multiplied);
}
#endif
for (size_t j=unopt_start; j<sample_count_per_channel_; j++) {
cdat[j] *= volume;
}
}
void SampleBuffer::transform_volume_for_sample(size_t sample_index, float volume)
{
for (int i=0;i<audio_params().channel_count();i++) {
transform_volume_for_sample_on_channel(sample_index, i, volume);
}
}
void SampleBuffer::transform_volume_for_sample_on_channel(size_t sample_index, int channel, float volume)
{
data_[channel][sample_index] *= volume;
}
void SampleBuffer::clamp()
{
for (int i=0; i<channel_count(); i++) {
clamp_channel(i);
}
}
void SampleBuffer::silence()
{
silence(0, sample_count_per_channel_);
}
void SampleBuffer::silence(size_t start_sample, size_t end_sample)
{
silence_bytes(start_sample * sizeof(float), end_sample * sizeof(float));
}
void SampleBuffer::silence_bytes(size_t start_byte, size_t end_byte)
{
if (!is_allocated()) {
qWarning() << "Tried to fill an unallocated sample buffer";
return;
}
for (int i=0;i<audio_params().channel_count();i++) {
memset(reinterpret_cast<char*>(data_[i].data()) + start_byte, 0, end_byte - start_byte);
}
}
void SampleBuffer::set(int channel, const float *data, size_t sample_offset, size_t sample_length)
{
if (!is_allocated()) {
qWarning() << "Tried to fill an unallocated sample buffer";
return;
}
memcpy(&data_[channel].data()[sample_offset], data, sizeof(float) * sample_length);
}
void SampleBuffer::clamp_channel(int channel)
{
const float min = -1.0f;
const float max = 1.0f;
float *cdat = data_[channel].data();
size_t unopt_start = 0;
#if defined(Q_PROCESSOR_X86) || defined(Q_PROCESSOR_ARM)
__m128 min_sse = _mm_load1_ps(&min);
__m128 max_sse = _mm_load1_ps(&max);
unopt_start = (sample_count_per_channel_ / 4) * 4;
for (size_t j=0; j<unopt_start; j+=4) {
float *here = cdat + j;
__m128 samples = _mm_loadu_ps(here);
samples = _mm_max_ps(samples, min_sse);
samples = _mm_min_ps(samples, max_sse);
_mm_storeu_ps(here, samples);
}
#endif
for (size_t sample=unopt_start; sample<sample_count(); sample++) {
float &s = data(channel)[sample];
s = std::clamp(s, min, max);
}
}
}
-114
View File
@@ -1,114 +0,0 @@
/***
Olive - Non-Linear Video Editor
Copyright (C) 2022 Olive Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#ifndef SAMPLEBUFFER_H
#define SAMPLEBUFFER_H
#include <memory>
#include "render/audioparams.h"
namespace olive {
/**
* @brief A buffer of audio samples
*
* Audio samples in this structure are always stored in PLANAR (separated by channel). This is done to simplify audio
* rendering code. This replaces the old system of using QByteArrays (containing packed audio) and while SampleBuffer
* replaces many of those in the rendering/processing side of things, QByteArrays are currently still in use for
* playback, including reading to and from the cache.
*/
class SampleBuffer
{
public:
SampleBuffer();
SampleBuffer(const AudioParams& audio_params, const rational& length);
SampleBuffer(const AudioParams& audio_params, size_t samples_per_channel);
const AudioParams& audio_params() const;
void set_audio_params(const AudioParams& params);
const size_t &sample_count() const { return sample_count_per_channel_; }
void set_sample_count(const size_t &sample_count);
void set_sample_count(const rational &length)
{
set_sample_count(audio_params_.time_to_samples(length));
}
float* data(int channel)
{
return data_[channel].data();
}
const float* data(int channel) const
{
return data_.at(channel).data();
}
std::vector<float *> to_raw_ptrs()
{
std::vector<float *> r(data_.size());
for (size_t i=0; i<r.size(); i++) {
r[i] = data_[i].data();
}
return r;
}
int channel_count() const { return data_.size(); }
bool is_allocated() const { return !data_.empty(); }
void allocate();
void destroy();
void reverse();
void speed(double speed);
void transform_volume(float f);
void transform_volume_for_channel(int channel, float volume);
void transform_volume_for_sample(size_t sample_index, float volume);
void transform_volume_for_sample_on_channel(size_t sample_index, int channel, float volume);
void clamp();
void silence();
void silence(size_t start_sample, size_t end_sample);
void silence_bytes(size_t start_byte, size_t end_byte);
void set(int channel, const float* data, size_t sample_offset, size_t sample_length);
void set(int channel, const float* data, size_t sample_length)
{
set(channel, data, 0, sample_length);
}
private:
void clamp_channel(int channel);
AudioParams audio_params_;
size_t sample_count_per_channel_;
std::vector< std::vector<float> > data_;
};
}
Q_DECLARE_METATYPE(olive::SampleBuffer)
#endif // SAMPLEBUFFER_H