Convert S32LE to S16LE for analyzer
This commit is contained in:
@@ -104,6 +104,10 @@ GstEngine::GstEngine(TaskManager *task_manager)
|
|||||||
GstEngine::~GstEngine() {
|
GstEngine::~GstEngine() {
|
||||||
EnsureInitialised();
|
EnsureInitialised();
|
||||||
current_pipeline_.reset();
|
current_pipeline_.reset();
|
||||||
|
if (latest_buffer_) {
|
||||||
|
gst_buffer_unref(latest_buffer_);
|
||||||
|
latest_buffer_ = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GstEngine::Init() {
|
bool GstEngine::Init() {
|
||||||
@@ -808,15 +812,15 @@ void GstEngine::UpdateScope(const int chunk_length) {
|
|||||||
|
|
||||||
scope_chunk_++;
|
scope_chunk_++;
|
||||||
|
|
||||||
if (buffer_format_ == "S16LE" ||
|
if (buffer_format_.startsWith("S16") ||
|
||||||
buffer_format_ == "S16BE" ||
|
buffer_format_.startsWith("S16") ||
|
||||||
buffer_format_ == "U16LE" ||
|
buffer_format_.startsWith("U16") ||
|
||||||
buffer_format_ == "U16BE" ||
|
buffer_format_.startsWith("S32")) {
|
||||||
buffer_format_ == "S16" ||
|
|
||||||
buffer_format_ == "U16")
|
|
||||||
memcpy(dest, source, bytes);
|
memcpy(dest, source, bytes);
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
memset(dest, 0, bytes);
|
memset(dest, 0, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
gst_buffer_unmap(latest_buffer_, &map);
|
gst_buffer_unmap(latest_buffer_, &map);
|
||||||
|
|
||||||
|
|||||||
@@ -274,10 +274,6 @@ bool GstEnginePipeline::InitAudioBin() {
|
|||||||
gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_EVENT_UPSTREAM, &EventHandoffCallback, this, nullptr);
|
gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_EVENT_UPSTREAM, &EventHandoffCallback, this, nullptr);
|
||||||
gst_object_unref(pad);
|
gst_object_unref(pad);
|
||||||
|
|
||||||
pad = gst_element_get_static_pad(queue_, "src");
|
|
||||||
gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_EVENT_UPSTREAM, SourceHandoffCallback, this, nullptr);
|
|
||||||
gst_object_unref(pad);
|
|
||||||
|
|
||||||
// Setting the equalizer bands:
|
// Setting the equalizer bands:
|
||||||
//
|
//
|
||||||
// GStreamer's GstIirEqualizerNBands sets up shelve filters for the first and last bands as corner cases.
|
// GStreamer's GstIirEqualizerNBands sets up shelve filters for the first and last bands as corner cases.
|
||||||
@@ -376,7 +372,6 @@ bool GstEnginePipeline::InitFromUrl(const QByteArray &stream_url, const QUrl ori
|
|||||||
stream_url_ = stream_url;
|
stream_url_ = stream_url;
|
||||||
original_url_ = original_url;
|
original_url_ = original_url;
|
||||||
end_offset_nanosec_ = end_nanosec;
|
end_offset_nanosec_ = end_nanosec;
|
||||||
format_.clear();
|
|
||||||
|
|
||||||
pipeline_ = engine_->CreateElement("playbin");
|
pipeline_ = engine_->CreateElement("playbin");
|
||||||
if (!pipeline_) return false;
|
if (!pipeline_) return false;
|
||||||
@@ -509,12 +504,10 @@ void GstEnginePipeline::StreamStartMessageReceived() {
|
|||||||
stream_url_ = next_stream_url_;
|
stream_url_ = next_stream_url_;
|
||||||
original_url_ = next_original_url_;
|
original_url_ = next_original_url_;
|
||||||
end_offset_nanosec_ = next_end_offset_nanosec_;
|
end_offset_nanosec_ = next_end_offset_nanosec_;
|
||||||
format_ = next_format_;
|
|
||||||
next_stream_url_.clear();
|
next_stream_url_.clear();
|
||||||
next_original_url_.clear();
|
next_original_url_.clear();
|
||||||
next_beginning_offset_nanosec_ = 0;
|
next_beginning_offset_nanosec_ = 0;
|
||||||
next_end_offset_nanosec_ = 0;
|
next_end_offset_nanosec_ = 0;
|
||||||
next_format_.clear();
|
|
||||||
|
|
||||||
emit EndOfStreamReached(id(), true);
|
emit EndOfStreamReached(id(), true);
|
||||||
}
|
}
|
||||||
@@ -769,11 +762,39 @@ GstPadProbeReturn GstEnginePipeline::PlaybinProbe(GstPad *pad, GstPadProbeInfo *
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GstPadProbeReturn GstEnginePipeline::HandoffCallback(GstPad*, GstPadProbeInfo *info, gpointer self) {
|
GstPadProbeReturn GstEnginePipeline::HandoffCallback(GstPad *pad, GstPadProbeInfo *info, gpointer self) {
|
||||||
|
|
||||||
GstEnginePipeline *instance = reinterpret_cast<GstEnginePipeline*>(self);
|
GstEnginePipeline *instance = reinterpret_cast<GstEnginePipeline*>(self);
|
||||||
|
|
||||||
|
GstCaps *caps = gst_pad_get_current_caps(pad);
|
||||||
|
GstStructure *structure = gst_caps_get_structure(caps, 0);
|
||||||
|
QString format = QString(gst_structure_get_string(structure, "format"));
|
||||||
|
int channels = 0;
|
||||||
|
int rate = 0;
|
||||||
|
gst_structure_get_int(structure, "channels", &channels);
|
||||||
|
gst_structure_get_int(structure, "rate", &rate);
|
||||||
|
|
||||||
GstBuffer *buf = gst_pad_probe_info_get_buffer(info);
|
GstBuffer *buf = gst_pad_probe_info_get_buffer(info);
|
||||||
|
GstBuffer *buf16 = nullptr;
|
||||||
|
|
||||||
|
if (format.startsWith("S32")) {
|
||||||
|
|
||||||
|
GstMapInfo map_info;
|
||||||
|
gst_buffer_map(buf, &map_info, GST_MAP_READ);
|
||||||
|
|
||||||
|
int32_t *s = (int32_t*) map_info.data;
|
||||||
|
int samples = (map_info.size / sizeof(int32_t)) / channels;
|
||||||
|
int buf16_size = samples * sizeof(int16_t) * channels;
|
||||||
|
int16_t *d = (int16_t*) g_malloc(buf16_size);
|
||||||
|
memset(d, 0, buf16_size);
|
||||||
|
for (int i = 0 ; i <= samples ; ++i) {
|
||||||
|
d[i] = (int16_t) (s[i] >> 16);
|
||||||
|
}
|
||||||
|
gst_buffer_unmap(buf, &map_info);
|
||||||
|
buf16 = gst_buffer_new_wrapped(d, buf16_size);
|
||||||
|
GST_BUFFER_DURATION(buf16) = GST_FRAMES_TO_CLOCK_TIME(samples * sizeof(int16_t) * channels, rate);
|
||||||
|
buf = buf16;
|
||||||
|
}
|
||||||
|
|
||||||
QList<GstBufferConsumer*> consumers;
|
QList<GstBufferConsumer*> consumers;
|
||||||
{
|
{
|
||||||
@@ -783,7 +804,11 @@ GstPadProbeReturn GstEnginePipeline::HandoffCallback(GstPad*, GstPadProbeInfo *i
|
|||||||
|
|
||||||
for (GstBufferConsumer *consumer : consumers) {
|
for (GstBufferConsumer *consumer : consumers) {
|
||||||
gst_buffer_ref(buf);
|
gst_buffer_ref(buf);
|
||||||
consumer->ConsumeBuffer(buf, instance->id(), instance->format_);
|
consumer->ConsumeBuffer(buf, instance->id(), format);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf16) {
|
||||||
|
gst_buffer_unref(buf16);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the end time of this buffer so we can stop playback if it's after the end time of this song.
|
// Calculate the end time of this buffer so we can stop playback if it's after the end time of this song.
|
||||||
@@ -800,7 +825,6 @@ GstPadProbeReturn GstEnginePipeline::HandoffCallback(GstPad*, GstPadProbeInfo *i
|
|||||||
instance->next_original_url_.clear();
|
instance->next_original_url_.clear();
|
||||||
instance->next_beginning_offset_nanosec_ = 0;
|
instance->next_beginning_offset_nanosec_ = 0;
|
||||||
instance->next_end_offset_nanosec_ = 0;
|
instance->next_end_offset_nanosec_ = 0;
|
||||||
instance->next_format_.clear();
|
|
||||||
|
|
||||||
// GstEngine will try to seek to the start of the new section, but we're already there so ignore it.
|
// GstEngine will try to seek to the start of the new section, but we're already there so ignore it.
|
||||||
instance->ignore_next_seek_ = true;
|
instance->ignore_next_seek_ = true;
|
||||||
@@ -817,25 +841,6 @@ GstPadProbeReturn GstEnginePipeline::HandoffCallback(GstPad*, GstPadProbeInfo *i
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GstPadProbeReturn GstEnginePipeline::SourceHandoffCallback(GstPad *pad, GstPadProbeInfo *, gpointer self) {
|
|
||||||
|
|
||||||
GstEnginePipeline *instance = reinterpret_cast<GstEnginePipeline*>(self);
|
|
||||||
|
|
||||||
GstCaps *caps = gst_pad_get_current_caps(pad);
|
|
||||||
GstStructure *structure = gst_caps_get_structure(caps, 0);
|
|
||||||
const gchar *format = gst_structure_get_string(structure, "format");
|
|
||||||
|
|
||||||
if (instance->next_uri_set_) {
|
|
||||||
instance->next_format_ = QString(format);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
instance->format_ = QString(format);
|
|
||||||
}
|
|
||||||
|
|
||||||
return GST_PAD_PROBE_OK;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
GstPadProbeReturn GstEnginePipeline::EventHandoffCallback(GstPad*, GstPadProbeInfo *info, gpointer self) {
|
GstPadProbeReturn GstEnginePipeline::EventHandoffCallback(GstPad*, GstPadProbeInfo *info, gpointer self) {
|
||||||
|
|
||||||
GstEnginePipeline *instance = reinterpret_cast<GstEnginePipeline*>(self);
|
GstEnginePipeline *instance = reinterpret_cast<GstEnginePipeline*>(self);
|
||||||
@@ -1122,7 +1127,6 @@ void GstEnginePipeline::SetNextUrl(const QByteArray &stream_url, const QUrl &ori
|
|||||||
next_original_url_ = original_url;
|
next_original_url_ = original_url;
|
||||||
next_beginning_offset_nanosec_ = beginning_nanosec;
|
next_beginning_offset_nanosec_ = beginning_nanosec;
|
||||||
next_end_offset_nanosec_ = end_nanosec;
|
next_end_offset_nanosec_ = end_nanosec;
|
||||||
next_format_.clear();
|
|
||||||
|
|
||||||
// Add request to discover the stream
|
// Add request to discover the stream
|
||||||
if (discoverer_) {
|
if (discoverer_) {
|
||||||
|
|||||||
@@ -223,10 +223,8 @@ signals:
|
|||||||
// The URL that is currently playing, and the URL that is to be preloaded when the current track is close to finishing.
|
// The URL that is currently playing, and the URL that is to be preloaded when the current track is close to finishing.
|
||||||
QByteArray stream_url_;
|
QByteArray stream_url_;
|
||||||
QUrl original_url_;
|
QUrl original_url_;
|
||||||
QString format_;
|
|
||||||
QByteArray next_stream_url_;
|
QByteArray next_stream_url_;
|
||||||
QUrl next_original_url_;
|
QUrl next_original_url_;
|
||||||
QString next_format_;
|
|
||||||
|
|
||||||
// If this is > 0 then the pipeline will be forced to stop when playback goes past this position.
|
// If this is > 0 then the pipeline will be forced to stop when playback goes past this position.
|
||||||
qint64 end_offset_nanosec_;
|
qint64 end_offset_nanosec_;
|
||||||
|
|||||||
Reference in New Issue
Block a user