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:
Jim Broadus 2021-01-05 15:38:08 -08:00 committed by John Maguire
parent 06066dfba4
commit 25d3fca079
2 changed files with 49 additions and 2 deletions

View File

@ -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;

View File

@ -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();