From 32d36d0e89e7d77a3127537bcbf1ad2e969bf09c Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Tue, 5 Oct 2021 10:46:26 -0300 Subject: [PATCH] smartencoder: Fix renegotiating when reencoding parts of the stream with vpx In the encoded streams we might not have all the information about the raw video stream, but when reencoding they end up being specified, even if those are default values. As vp8 decoders always output frames in some YUV color space we can ensure that when upstream doesn't specify any value in its caps we use the default one which is what we end up doing when decoding/reencoding anyway, so this way downstream (matroskamux in that case) doesn't need to be able to renegotiate (which it doesn't). Part-of: --- .../gst/encoding/gstsmartencoder.c | 64 ++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/subprojects/gst-plugins-base/gst/encoding/gstsmartencoder.c b/subprojects/gst-plugins-base/gst/encoding/gstsmartencoder.c index 18245973f1..ea1a8a90cb 100644 --- a/subprojects/gst-plugins-base/gst/encoding/gstsmartencoder.c +++ b/subprojects/gst-plugins-base/gst/encoding/gstsmartencoder.c @@ -23,6 +23,7 @@ #endif #include +#include #include "gstsmartencoder.h" GST_DEBUG_CATEGORY_STATIC (smart_encoder_debug); @@ -497,6 +498,66 @@ beach: return res; } +static GstCaps * +smart_encoder_get_caps (GstSmartEncoder * self, GstCaps * original_caps) +{ + gint i; + GstCaps *caps, *outcaps; + GstStructure *original_struct = gst_caps_get_structure (original_caps, 0); + GstStructure *out_struct, *_struct; + GstVideoInfo info; + static const gchar *default_fields[] = { + "pixel-aspect-ratio", + "framerate", + "interlace-mode", + "colorimetry", + "chroma-site", + "multiview-mode", + "multiview-flags", + }; + + if (!gst_structure_has_name (original_struct, "video/x-vp8")) { + + return gst_caps_ref (original_caps); + } + + /* VP8 is always decoded into YUV colorspaces and we support VP9 profiles + * where only YUV is supported (0 and 2) so we ensure that all the + * default fields for video/x-raw are set on the caps if none provided by + * upstream. This allows us to allow renegotiating new caps downstream when + * switching from no reencoding to reencoding making sure all the fields are + * defined all the time + */ + caps = gst_caps_copy (original_caps); + _struct = gst_caps_get_structure (caps, 0); + gst_structure_set_name (_struct, "video/x-raw"); + gst_structure_set (_struct, + "format", G_TYPE_STRING, "I420", + "multiview-mode", G_TYPE_STRING, "mono", + "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET, + GST_VIDEO_MULTIVIEW_FLAGS_NONE, GST_FLAG_SET_MASK_EXACT, NULL); + + gst_video_info_from_caps (&info, caps); + gst_caps_unref (caps); + caps = gst_video_info_to_caps (&info); + _struct = gst_caps_get_structure (caps, 0); + + outcaps = gst_caps_copy (original_caps); + out_struct = gst_caps_get_structure (outcaps, 0); + for (i = 0; i < G_N_ELEMENTS (default_fields); i++) { + const gchar *field = default_fields[i]; + + if (!gst_structure_has_field (original_struct, field)) { + const GValue *v = gst_structure_get_value (_struct, field); + g_assert (v); + gst_structure_set_value (out_struct, field, v); + } + } + gst_caps_unref (caps); + + return outcaps; +} + static gboolean smart_encoder_sink_event (GstPad * pad, GstObject * ghostpad, GstEvent * event) { @@ -515,7 +576,8 @@ smart_encoder_sink_event (GstPad * pad, GstObject * ghostpad, GstEvent * event) if (self->original_caps) gst_caps_unref (self->original_caps); - self->original_caps = gst_caps_ref (caps); + + self->original_caps = smart_encoder_get_caps (self, caps); self->push_original_caps = TRUE; gst_clear_event (&event); break;