diff --git a/src/moodbar/moodbarbuilder.cpp b/src/moodbar/moodbarbuilder.cpp index 55351725..fc98daf4 100644 --- a/src/moodbar/moodbarbuilder.cpp +++ b/src/moodbar/moodbarbuilder.cpp @@ -22,6 +22,9 @@ #include #include +#include +#include + #include #include @@ -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) { if (size > barkband_table_.length()) { diff --git a/src/moodbar/moodbarbuilder.h b/src/moodbar/moodbarbuilder.h index 9e7b481e..09c73f36 100644 --- a/src/moodbar/moodbarbuilder.h +++ b/src/moodbar/moodbarbuilder.h @@ -22,6 +22,8 @@ #ifndef MOODBARBUILDER_H #define MOODBARBUILDER_H +#include + #include #include #include @@ -31,6 +33,7 @@ class MoodbarBuilder { explicit MoodbarBuilder(); 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); QByteArray Finish(const int width); diff --git a/src/moodbar/moodbarpipeline.cpp b/src/moodbar/moodbarpipeline.cpp index efb7aca7..a211da45 100644 --- a/src/moodbar/moodbarpipeline.cpp +++ b/src/moodbar/moodbarpipeline.cpp @@ -99,7 +99,7 @@ void MoodbarPipeline::Start() { GstElement *decodebin = CreateElement(QStringLiteral("uridecodebin")); convert_element_ = CreateElement(QStringLiteral("audioconvert")); - GstElement *spectrum = CreateElement(QStringLiteral("fastspectrum")); + GstElement *spectrum = CreateElement(QStringLiteral("spectrum")); GstElement *fakesink = CreateElement(QStringLiteral("fakesink")); if (!decodebin || !convert_element_ || !spectrum || !fakesink) { @@ -118,7 +118,7 @@ void MoodbarPipeline::Start() { return; } - builder_ = make_unique(); + //builder_ = make_unique(); // Set properties @@ -126,8 +126,16 @@ void MoodbarPipeline::Start() { g_object_set(decodebin, "uri", gst_url.constData(), nullptr); g_object_set(spectrum, "bands", kBands, nullptr); - GstStrawberryFastSpectrum *fastspectrum = reinterpret_cast(spectrum); - fastspectrum->output_callback = [this](double *magnitudes, const int size) { builder_->AddFrame(magnitudes, size); }; + //GstStrawberryFastSpectrum *fastspectrum = reinterpret_cast(spectrum); + //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 CHECKED_GCONNECT(decodebin, "pad-added", &NewPadCallback, this); @@ -206,6 +214,20 @@ GstBusSyncReply MoodbarPipeline::BusCallbackSync(GstBus *bus, GstMessage *messag MoodbarPipeline *instance = reinterpret_cast(self); 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: instance->Stop(true); 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(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(map.data), map.size); + gst_buffer_unmap(buffer, &map); + gst_buffer_unref(buffer); + + return GST_PAD_PROBE_OK; + +} + void MoodbarPipeline::Stop(const bool success) { success_ = success; diff --git a/src/moodbar/moodbarpipeline.h b/src/moodbar/moodbarpipeline.h index bac39cfc..516eb367 100644 --- a/src/moodbar/moodbarpipeline.h +++ b/src/moodbar/moodbarpipeline.h @@ -62,6 +62,7 @@ class MoodbarPipeline : public QObject { static void NewPadCallback(GstElement *element, GstPad *pad, gpointer self); static GstBusSyncReply BusCallbackSync(GstBus *bus, GstMessage *message, gpointer self); + static GstPadProbeReturn BufferProbeCallback(GstPad *pad, GstPadProbeInfo *info, gpointer self); private: QUrl url_; @@ -73,6 +74,7 @@ class MoodbarPipeline : public QObject { bool success_; bool running_; QByteArray data_; + gint buffer_probe_cb_id_; }; #endif // MOODBARPIPELINE_H