Use spectrum plugin for moodbar
This commit is contained in:
parent
fa96cdfaea
commit
7e0231cb77
|
@ -22,6 +22,9 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <gst/gst.h>
|
||||||
|
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
|
|
||||||
|
@ -61,6 +64,29 @@ void MoodbarBuilder::Init(const int bands, const int rate_hz) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MoodbarBuilder::AddFrame(const GValue *magnitudes, const int size) {
|
||||||
|
|
||||||
|
if (size > barkband_table_.length()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate total magnitudes for different bark bands.
|
||||||
|
double bands[sBarkBandCount]{};
|
||||||
|
for (int i = 0; i < size; ++i) {
|
||||||
|
const GValue *magnitude = gst_value_list_get_value(magnitudes, i);
|
||||||
|
bands[barkband_table_[i]] += g_value_get_float(magnitude);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now divide the bark bands into thirds and compute their total amplitudes.
|
||||||
|
double rgb[] = { 0, 0, 0 };
|
||||||
|
for (int i = 0; i < sBarkBandCount; ++i) {
|
||||||
|
rgb[(i * 3) / sBarkBandCount] += bands[i] * bands[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
frames_.append(Rgb(sqrt(rgb[0]), sqrt(rgb[1]), sqrt(rgb[2])));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void MoodbarBuilder::AddFrame(const double *magnitudes, const int size) {
|
void MoodbarBuilder::AddFrame(const double *magnitudes, const int size) {
|
||||||
|
|
||||||
if (size > barkband_table_.length()) {
|
if (size > barkband_table_.length()) {
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
#ifndef MOODBARBUILDER_H
|
#ifndef MOODBARBUILDER_H
|
||||||
#define MOODBARBUILDER_H
|
#define MOODBARBUILDER_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
|
@ -31,6 +33,7 @@ class MoodbarBuilder {
|
||||||
explicit MoodbarBuilder();
|
explicit MoodbarBuilder();
|
||||||
|
|
||||||
void Init(const int bands, const int rate_hz);
|
void Init(const int bands, const int rate_hz);
|
||||||
|
void AddFrame(const GValue *magnitudes, const int size);
|
||||||
void AddFrame(const double *magnitudes, const int size);
|
void AddFrame(const double *magnitudes, const int size);
|
||||||
QByteArray Finish(const int width);
|
QByteArray Finish(const int width);
|
||||||
|
|
||||||
|
|
|
@ -99,7 +99,7 @@ void MoodbarPipeline::Start() {
|
||||||
|
|
||||||
GstElement *decodebin = CreateElement(QStringLiteral("uridecodebin"));
|
GstElement *decodebin = CreateElement(QStringLiteral("uridecodebin"));
|
||||||
convert_element_ = CreateElement(QStringLiteral("audioconvert"));
|
convert_element_ = CreateElement(QStringLiteral("audioconvert"));
|
||||||
GstElement *spectrum = CreateElement(QStringLiteral("fastspectrum"));
|
GstElement *spectrum = CreateElement(QStringLiteral("spectrum"));
|
||||||
GstElement *fakesink = CreateElement(QStringLiteral("fakesink"));
|
GstElement *fakesink = CreateElement(QStringLiteral("fakesink"));
|
||||||
|
|
||||||
if (!decodebin || !convert_element_ || !spectrum || !fakesink) {
|
if (!decodebin || !convert_element_ || !spectrum || !fakesink) {
|
||||||
|
@ -118,7 +118,7 @@ void MoodbarPipeline::Start() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
builder_ = make_unique<MoodbarBuilder>();
|
//builder_ = make_unique<MoodbarBuilder>();
|
||||||
|
|
||||||
// Set properties
|
// Set properties
|
||||||
|
|
||||||
|
@ -126,8 +126,16 @@ void MoodbarPipeline::Start() {
|
||||||
g_object_set(decodebin, "uri", gst_url.constData(), nullptr);
|
g_object_set(decodebin, "uri", gst_url.constData(), nullptr);
|
||||||
g_object_set(spectrum, "bands", kBands, nullptr);
|
g_object_set(spectrum, "bands", kBands, nullptr);
|
||||||
|
|
||||||
GstStrawberryFastSpectrum *fastspectrum = reinterpret_cast<GstStrawberryFastSpectrum*>(spectrum);
|
//GstStrawberryFastSpectrum *fastspectrum = reinterpret_cast<GstStrawberryFastSpectrum*>(spectrum);
|
||||||
fastspectrum->output_callback = [this](double *magnitudes, const int size) { builder_->AddFrame(magnitudes, size); };
|
//fastspectrum->output_callback = [this](double *magnitudes, const int size) { builder_->AddFrame(magnitudes, size); };
|
||||||
|
|
||||||
|
{
|
||||||
|
GstPad *pad = gst_element_get_static_pad(fakesink, "src");
|
||||||
|
if (pad) {
|
||||||
|
buffer_probe_cb_id_ = gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER, BufferProbeCallback, this, nullptr);
|
||||||
|
gst_object_unref(pad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Connect signals
|
// Connect signals
|
||||||
CHECKED_GCONNECT(decodebin, "pad-added", &NewPadCallback, this);
|
CHECKED_GCONNECT(decodebin, "pad-added", &NewPadCallback, this);
|
||||||
|
@ -206,6 +214,20 @@ GstBusSyncReply MoodbarPipeline::BusCallbackSync(GstBus *bus, GstMessage *messag
|
||||||
MoodbarPipeline *instance = reinterpret_cast<MoodbarPipeline*>(self);
|
MoodbarPipeline *instance = reinterpret_cast<MoodbarPipeline*>(self);
|
||||||
|
|
||||||
switch (GST_MESSAGE_TYPE(message)) {
|
switch (GST_MESSAGE_TYPE(message)) {
|
||||||
|
#if 0
|
||||||
|
case GST_MESSAGE_ELEMENT:{
|
||||||
|
const GstStructure *structure = gst_message_get_structure(message);
|
||||||
|
const gchar *name = gst_structure_get_name(structure);
|
||||||
|
if (strcmp(name, "spectrum") == 0) {
|
||||||
|
const GValue *magnitudes = gst_structure_get_value(structure, "magnitude");
|
||||||
|
if (instance->builder_) {
|
||||||
|
instance->builder_->AddFrame(magnitudes, kBands);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
case GST_MESSAGE_EOS:
|
case GST_MESSAGE_EOS:
|
||||||
instance->Stop(true);
|
instance->Stop(true);
|
||||||
break;
|
break;
|
||||||
|
@ -223,6 +245,24 @@ GstBusSyncReply MoodbarPipeline::BusCallbackSync(GstBus *bus, GstMessage *messag
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GstPadProbeReturn MoodbarPipeline::BufferProbeCallback(GstPad *pad, GstPadProbeInfo *info, gpointer self) {
|
||||||
|
|
||||||
|
Q_UNUSED(pad)
|
||||||
|
|
||||||
|
MoodbarPipeline *instance = reinterpret_cast<MoodbarPipeline*>(self);
|
||||||
|
|
||||||
|
GstBuffer *buffer = gst_pad_probe_info_get_buffer(info);
|
||||||
|
|
||||||
|
GstMapInfo map;
|
||||||
|
gst_buffer_map(buffer, &map, GST_MAP_READ);
|
||||||
|
instance->data_.append(reinterpret_cast<const char*>(map.data), map.size);
|
||||||
|
gst_buffer_unmap(buffer, &map);
|
||||||
|
gst_buffer_unref(buffer);
|
||||||
|
|
||||||
|
return GST_PAD_PROBE_OK;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void MoodbarPipeline::Stop(const bool success) {
|
void MoodbarPipeline::Stop(const bool success) {
|
||||||
|
|
||||||
success_ = success;
|
success_ = success;
|
||||||
|
|
|
@ -62,6 +62,7 @@ class MoodbarPipeline : public QObject {
|
||||||
|
|
||||||
static void NewPadCallback(GstElement *element, GstPad *pad, gpointer self);
|
static void NewPadCallback(GstElement *element, GstPad *pad, gpointer self);
|
||||||
static GstBusSyncReply BusCallbackSync(GstBus *bus, GstMessage *message, gpointer self);
|
static GstBusSyncReply BusCallbackSync(GstBus *bus, GstMessage *message, gpointer self);
|
||||||
|
static GstPadProbeReturn BufferProbeCallback(GstPad *pad, GstPadProbeInfo *info, gpointer self);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QUrl url_;
|
QUrl url_;
|
||||||
|
@ -73,6 +74,7 @@ class MoodbarPipeline : public QObject {
|
||||||
bool success_;
|
bool success_;
|
||||||
bool running_;
|
bool running_;
|
||||||
QByteArray data_;
|
QByteArray data_;
|
||||||
|
gint buffer_probe_cb_id_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MOODBARPIPELINE_H
|
#endif // MOODBARPIPELINE_H
|
||||||
|
|
Loading…
Reference in New Issue