gstengine: Fix output audio depth
When the decoder bin's src pad becomes available, check its caps for a format. If the format is not S16LE, then apply F32LE caps before the tee. This prevents the pipeline from negotiating S16LE when the decoder produces other formats.
This commit is contained in:
parent
06066dfba4
commit
25d3fca079
@ -850,20 +850,59 @@ void GstEnginePipeline::BufferingMessageReceived(GstMessage* msg) {
|
||||
}
|
||||
}
|
||||
|
||||
QString GstEnginePipeline::GetAudioFormat(GstCaps* caps) {
|
||||
const guint sz = gst_caps_get_size(caps);
|
||||
for (int i = 0; i < sz; i++) {
|
||||
GstStructure* s = gst_caps_get_structure(caps, i);
|
||||
if (strcmp(gst_structure_get_name(s), "audio/x-raw") == 0) {
|
||||
const gchar* fmt = gst_structure_get_string(s, "format");
|
||||
if (fmt != nullptr) {
|
||||
return QString::fromUtf8(fmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void GstEnginePipeline::NewPadCallback(GstElement*, GstPad* pad,
|
||||
gpointer self) {
|
||||
GstEnginePipeline* instance = reinterpret_cast<GstEnginePipeline*>(self);
|
||||
GstPad* const audiopad =
|
||||
gst_element_get_static_pad(instance->audiobin_, "sink");
|
||||
|
||||
// Link decodebin's sink pad to audiobin's src pad.
|
||||
qLog(Debug) << "Decoder bin pad added:" << GST_PAD_NAME(pad);
|
||||
|
||||
// Make sure the audio bin isn't already linked to something.
|
||||
if (GST_PAD_IS_LINKED(audiopad)) {
|
||||
qLog(Warning) << instance->id()
|
||||
<< "audiopad is already linked, unlinking old pad";
|
||||
gst_pad_unlink(audiopad, GST_PAD_PEER(audiopad));
|
||||
}
|
||||
|
||||
gst_pad_link(pad, audiopad);
|
||||
// See what the decoder bin wants to output.
|
||||
GstCaps* caps = gst_pad_get_current_caps(pad);
|
||||
if (caps) {
|
||||
gchar* caps_str = gst_caps_to_string(caps);
|
||||
qLog(Debug) << "Current caps:" << caps_str;
|
||||
g_free(caps_str);
|
||||
|
||||
QString fmt = GetAudioFormat(caps);
|
||||
|
||||
// The output branch only handles F32LE and S16LE. If the source is S16LE,
|
||||
// then use that throughout the pipeline. Otherwise, use F32LE.
|
||||
if (fmt != "S16LE") {
|
||||
GstCaps* new_caps = gst_caps_new_simple("audio/x-raw", "format",
|
||||
G_TYPE_STRING, "F32LE", nullptr);
|
||||
g_object_set(instance->capsfilter_, "caps", new_caps, nullptr);
|
||||
gst_caps_unref(new_caps);
|
||||
}
|
||||
gst_caps_unref(caps);
|
||||
}
|
||||
|
||||
// Link decodebin's sink pad to audiobin's src pad.
|
||||
if (gst_pad_link(pad, audiopad) != GST_PAD_LINK_OK) {
|
||||
qLog(Error) << "Failed to link decoder to audio bin.";
|
||||
}
|
||||
gst_object_unref(audiopad);
|
||||
|
||||
// Offset the timestamps on all the buffers coming out of the decodebin so
|
||||
@ -1100,6 +1139,11 @@ void GstEnginePipeline::TransitionToNext() {
|
||||
|
||||
ignore_tags_ = true;
|
||||
|
||||
// Reset the caps filter
|
||||
GstCaps* new_caps = gst_caps_new_any();
|
||||
g_object_set(capsfilter_, "caps", new_caps, nullptr);
|
||||
gst_caps_unref(new_caps);
|
||||
|
||||
if (!ReplaceDecodeBin(next_.url_)) {
|
||||
qLog(Error) << "ReplaceDecodeBin failed with " << next_.url_;
|
||||
return;
|
||||
|
@ -168,6 +168,9 @@ class GstEnginePipeline : public QObject {
|
||||
// a src pad immediately and we can link it after everything's created.
|
||||
void MaybeLinkDecodeToAudio();
|
||||
|
||||
// Helper method to retrieve the audio format from a GstCaps object.
|
||||
static QString GetAudioFormat(GstCaps* caps);
|
||||
|
||||
private slots:
|
||||
void FaderTimelineFinished();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user