From 6d34ab7f9e7db677085b16f5fa2dbcdc211626ce Mon Sep 17 00:00:00 2001 From: suryaiyappan2k Date: Fri, 10 Jul 2026 14:43:35 +0530 Subject: [PATCH] RDKEMW-6776 Encrypted Pipeline Changes with SVPPAY on AAMP Reason for change: To insert the svppayload element into encrypted pipeline immediately after the aampdecryptor element. Test procedure: Test playback across all the apps. Risks: Low. --- InterfacePlayerRDK.cpp | 113 +++++++++ gst-plugins/drm/gst/gstcdmidecryptor.cpp | 239 +++++++++++++++++- gst-plugins/drm/gst/gstcdmidecryptor.h | 24 ++ gst-plugins/drm/gst/gstplayreadydecryptor.cpp | 37 ++- gst-plugins/drm/gst/gstwidevinedecryptor.cpp | 36 ++- 5 files changed, 420 insertions(+), 29 deletions(-) diff --git a/InterfacePlayerRDK.cpp b/InterfacePlayerRDK.cpp index 3dd8e559..bd52dba5 100644 --- a/InterfacePlayerRDK.cpp +++ b/InterfacePlayerRDK.cpp @@ -2080,6 +2080,7 @@ static void element_setup_cb(void *playbin, void *element, void *instance) g_free(elemName); } + /** * @brief Initialize properties/callback of appsrc * @param[in] _this pointer to InterfacePlayerRDK instance associated with the playback @@ -2235,6 +2236,113 @@ GstFlowReturn InterfacePlayerRDK_OnVideoSample(GstElement* object, void *_this) return GST_FLOW_OK; } +// Pad probe callback +static GstPadProbeReturn +on_decryptor_src_pad_event(GstPad *pad, GstPadProbeInfo *info, gpointer user_data) +{ + g_print("patch 0005 applied: surya - on_decryptor_src_pad_event\n"); + GstEvent *event = GST_PAD_PROBE_INFO_EVENT(info); + + if (!(GST_PAD_PROBE_INFO_TYPE(info) & GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM)) + return GST_PAD_PROBE_OK; + + if (GST_EVENT_TYPE(event) != GST_EVENT_CAPS) + { + return GST_PAD_PROBE_OK; + } + + GstElement *decryptor = GST_ELEMENT(user_data); + GstPad *srcpad = gst_element_get_static_pad(decryptor, "src"); + if (!srcpad) + { + MW_LOG_ERR("Failed to retrieve 'src' pad from decryptor '%s'.", GST_ELEMENT_NAME(decryptor)); + g_print("patch 0005 applied: surya - failed to retrieve src pad from decryptor %s\n", GST_ELEMENT_NAME(decryptor)); + return GST_PAD_PROBE_REMOVE; + } + + GstPad *peer = gst_pad_get_peer(srcpad); + if (!peer) + { + MW_LOG_ERR("No downstream peer connected to decryptor '%s'.", GST_ELEMENT_NAME(decryptor)); + gst_object_unref(srcpad); + return GST_PAD_PROBE_REMOVE; + } + + GstElement *parent = GST_ELEMENT(gst_element_get_parent(decryptor)); + if (!parent) + { + MW_LOG_ERR("Failed to get parent bin of decryptor '%s'.", GST_ELEMENT_NAME(decryptor)); + g_print("patch 0005 applied: surya - failed to get parent bin of decryptor %s\n", GST_ELEMENT_NAME(decryptor)); + gst_object_unref(srcpad); + gst_object_unref(peer); + return GST_PAD_PROBE_REMOVE; + } + + GstElement *svppay = gst_element_factory_make("svppay", NULL); + if (!svppay) + { + MW_LOG_ERR("Failed to create 'svppay' element."); + g_print("patch 0005 applied: surya - failed to create svppay element\n"); + gst_object_unref(srcpad); + gst_object_unref(peer); + return GST_PAD_PROBE_REMOVE; + } + g_print("patch 0005 applied: surya - successfully created svppay element\n"); + + gst_bin_add(GST_BIN(parent), svppay); + gst_element_sync_state_with_parent(svppay); + + GstPad *svppay_sink = gst_element_get_static_pad(svppay, "sink"); + GstPad *svppay_src = gst_element_get_static_pad(svppay, "src"); + + if (!gst_pad_unlink(srcpad, peer)) + { + MW_LOG_ERR("Failed to unlink decryptor '%s' from its peer.", GST_ELEMENT_NAME(decryptor)); + } + + if (gst_pad_link(srcpad, svppay_sink) != GST_PAD_LINK_OK) + { + MW_LOG_ERR("Failed to link decryptor '%s' to svppay.", GST_ELEMENT_NAME(decryptor)); + } + else if (gst_pad_link(svppay_src, peer) != GST_PAD_LINK_OK) + { + MW_LOG_ERR("Failed to link svppay to downstream peer."); + } + else + { + MW_LOG_INFO("'svppay' inserted after decryptor '%s'.", GST_ELEMENT_NAME(decryptor)); + g_print("patch 0005 applied: surya - svppay inserted after decryptor %s\n", GST_ELEMENT_NAME(decryptor)); + } + + gst_object_unref(srcpad); + gst_object_unref(peer); + gst_object_unref(svppay_sink); + gst_object_unref(svppay_src); + + return GST_PAD_PROBE_REMOVE; // done with the probe +} + +static void element_setup_cb_svppay(GstElement *playbin, GstElement *element, gpointer user_data) +{ + const gchar *name = gst_element_get_name(element); + g_print("Patch applied: surya - element_setup_cb_svppay\n"); + MW_LOG_INFO("surya - Received element: %s", name); + + if (name && strstr(name, "decryptor")) + { + GstPad *srcpad = gst_element_get_static_pad(element, "src"); + if (!srcpad) + { + MW_LOG_ERR("Unable to retrieve 'src' pad from element: %s\n", GST_ELEMENT_NAME(element)); + g_print("patch 0005 surya: unable to retrieve src pad from element %s\n", GST_ELEMENT_NAME(element)); + return; + } + gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, + on_decryptor_src_pad_event, element, NULL); + gst_object_unref(srcpad); + } +} + /** * @fn SetupClosedCaptionControlStream */ @@ -2524,6 +2632,11 @@ int InterfacePlayerRDK::SetupStream(int streamId, void *playerInstance, std::st // Send the media_stream object so that qtdemux can be instantly mapped to media type without caps/parent check g_signal_connect(stream->sinkbin, "element_setup", G_CALLBACK(element_setup_cb), pInterfacePlayerRDK); } + if (eGST_MEDIATYPE_VIDEO == streamId) + { + g_print("surya - patch applied: SVPPAY callback started\n"); + g_signal_connect(stream->sinkbin, "element_setup", G_CALLBACK(element_setup_cb_svppay), pInterfacePlayerRDK); + } if (eGST_MEDIATYPE_VIDEO == streamId && (mediaFormat==eGST_MEDIAFORMAT_DASH || mediaFormat==eGST_MEDIAFORMAT_HLS_MP4)) { // enable multiqueue diff --git a/gst-plugins/drm/gst/gstcdmidecryptor.cpp b/gst-plugins/drm/gst/gstcdmidecryptor.cpp index 5c3a36fb..f2e1220e 100755 --- a/gst-plugins/drm/gst/gstcdmidecryptor.cpp +++ b/gst-plugins/drm/gst/gstcdmidecryptor.cpp @@ -125,7 +125,184 @@ static unsigned char* ReplaceKIDPsshData(const unsigned char *InputData, const s return NULL; } -static const gchar *srcMimeTypes[] = { "video/x-h264", "video/x-h264(memory:SecMem)", "audio/mpeg", "video/x-h265", "video/x-h265(memory:SecMem)", "audio/x-eac3", "audio/x-gst-fourcc-ec_3", "audio/x-ac3","audio/x-opus", nullptr }; +/* Base video/audio media types supported by all platforms */ +static const gchar *baseMimeTypes[] = { + "video/x-h264", "video/x-h265", + "audio/mpeg", "audio/x-eac3", "audio/x-gst-fourcc-ec_3", "audio/x-ac3", "audio/x-opus", + nullptr +}; + +/* + * Platform-aware OCDM caps transform function, resolved via dlsym at class_init. + * Each platform's OCDM implementation adds its secure-memory feature to the caps + * (e.g. "(memory:MediaTekSecure)" for MTK, "(memory:SecMem)" for Amlogic). + */ +static OpenCDMError(*OCDMGstTransformCaps)(GstCaps **) = nullptr; + +/* + * srcMimeTypes is built dynamically at init time to include platform-specific + * secure memory feature variants (e.g. "(memory:MediaTekSecure)", "(memory:SecMem)"). + * This avoids hardcoding platform-specific memory feature strings here. + * Access only after gst_cdmidecryptor_init_src_mime_types() has been called. + */ +static GPtrArray *srcMimeTypesArray = nullptr; +static const gchar **srcMimeTypes = nullptr; + +/* + * Platform secure memory feature string discovered at runtime by probing + * OCDMGstTransformCaps with a dummy caps. Empty string if not applicable. + * e.g. "memory:MediaTekSecure", "memory:SecMem" + */ +static gchar *platformSecureMemFeature = nullptr; + +/** + * Discover the platform-specific GStreamer memory feature string by probing + * OCDMGstTransformCaps with a dummy video/x-h264 caps. + * Sets platformSecureMemFeature if a non-ANY caps feature is found. + * Must be called after OCDMGstTransformCaps is resolved via dlsym. + */ +static void gst_cdmidecryptor_discover_platform_memory_feature(void) +{ + g_print("surya - gst_cdmidecryptor_discover_platform_memory_feature\n"); + if (platformSecureMemFeature != nullptr) + return; /* already discovered */ + + if (!OCDMGstTransformCaps) + { + GST_INFO("OCDMGstTransformCaps not available; no platform memory feature to discover"); + platformSecureMemFeature = g_strdup(""); /* mark as done, no feature */ + return; + } + + GstCaps *probeCaps = gst_caps_from_string("video/x-h264"); + if (!probeCaps) + { + GST_WARNING("Failed to create probe caps for memory feature discovery"); + platformSecureMemFeature = g_strdup(""); + return; + } + + OpenCDMError ret = OCDMGstTransformCaps(&probeCaps); + if (ret == ERROR_NONE && probeCaps && gst_caps_get_size(probeCaps) > 0) + { + /* + * Extract the memory feature by converting caps to string and parsing it. + * e.g. "video/x-h264(memory:MediaTekSecure)" → extract "memory:MediaTekSecure" + * This avoids gst_caps_features_nth / gst_caps_features_nth_name which are + * unavailable in older GStreamer versions. + */ + gchar *capsStr = gst_caps_to_string(probeCaps); + if (capsStr) + { + /* Look for opening parenthesis of a caps feature */ + const gchar *open = g_strstr_len(capsStr, -1, "("); + const gchar *close = open ? g_strstr_len(open, -1, ")") : NULL; + if (open && close && close > open + 1) + { + gchar *feature = g_strndup(open + 1, close - open - 1); + /* Ignore the standard system memory feature */ + if (g_strcmp0(feature, GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY) != 0) + { + platformSecureMemFeature = feature; + GST_INFO("gst_cdmidecryptor: discovered platform secure memory feature: '%s'", platformSecureMemFeature); + } + else + { + g_free(feature); + } + } + g_free(capsStr); + } + } + + gst_caps_unref(probeCaps); + + if (!platformSecureMemFeature) + { + platformSecureMemFeature = g_strdup(""); /* no special memory feature on this platform */ + GST_INFO("gst_cdmidecryptor: no platform-specific memory feature detected"); + } + +} + +/** + * Build the srcMimeTypes array dynamically based on baseMimeTypes and + * the discovered platform memory feature. Only video types get the secure + * memory feature variant (audio does not use secure memory). + */ +static void gst_cdmidecryptor_init_src_mime_types(void) +{ + g_print("surya - patch applied for gst_cdmidecryptor_init_src_mime_types\n"); + if (srcMimeTypesArray != nullptr) + return; /* already initialised */ + + srcMimeTypesArray = g_ptr_array_new_with_free_func(g_free); + + for (int i = 0; baseMimeTypes[i]; i++) + { + /* Always add the plain (non-secure) variant */ + g_ptr_array_add(srcMimeTypesArray, g_strdup(baseMimeTypes[i])); + + /* For video types, also add the platform-specific secure memory variant */ + if (platformSecureMemFeature && platformSecureMemFeature[0] != '\0' && + g_str_has_prefix(baseMimeTypes[i], "video/")) + { + gchar *secureType = g_strdup_printf("%s(%s)", baseMimeTypes[i], platformSecureMemFeature); + g_ptr_array_add(srcMimeTypesArray, secureType); + } + } + + /* null-terminate so it can be used as a C-style const gchar* array */ + g_ptr_array_add(srcMimeTypesArray, nullptr); + srcMimeTypes = (const gchar **)srcMimeTypesArray->pdata; + GST_INFO("gst_cdmidecryptor: srcMimeTypes built with %u entries (platform feature: '%s')", + srcMimeTypesArray->len - 1, + platformSecureMemFeature ? platformSecureMemFeature : "(none)"); +} + +/** + * Public API: return the discovered platform memory feature string. + * Callers must NOT free the returned pointer. + */ +const gchar *gst_cdmidecryptor_get_platform_memory_feature(void) +{ + g_print("surya - Patch applied for gst_cdmidecryptor_get_platform_memory_feature\n"); + return platformSecureMemFeature; +} + +/** + * Public API: build a dynamic caps string for the src pad of a decryptor element. + * + * Produces plain variants for all base media types plus one + * "(memory:)" variant for each video type when platformMemFeature is set. + * + * Example output (MTK): + * "video/x-h264; video/x-h264(memory:MediaTekSecure); audio/mpeg; ..." + * + * The caller is responsible for freeing the returned string with g_free(). + */ +gchar *gst_cdmidecryptor_build_src_caps_string(const gchar *platformMemFeature) +{ + GString *capsStr = g_string_new(nullptr); + gboolean first = TRUE; + g_print("surya - Patch applied for gst_cdmidecryptor_build_src_caps_string\n"); + for (int i = 0; baseMimeTypes[i]; i++) + { + if (!first) + g_string_append(capsStr, "; "); + g_string_append(capsStr, baseMimeTypes[i]); + first = FALSE; + + /* Add secure-memory variant for video types */ + if (platformMemFeature && platformMemFeature[0] != '\0' && + g_str_has_prefix(baseMimeTypes[i], "video/")) + { + g_string_append_printf(capsStr, "; %s(%s)", baseMimeTypes[i], platformMemFeature); + } + } + + return g_string_free(capsStr, FALSE); /* transfer: full */ +} /* class initialization */ G_DEFINE_TYPE_WITH_CODE (GstCDMIDecryptor, gst_cdmidecryptor, GST_TYPE_BASE_TRANSFORM, @@ -158,7 +335,6 @@ static void gst_cdmidecryptor_set_property(GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static gboolean gst_cdmidecryptor_accept_caps(GstBaseTransform * trans, GstPadDirection direction, GstCaps * caps); -static OpenCDMError(*OCDMGstTransformCaps)(GstCaps **); static void gst_cdmidecryptor_class_init( GstCDMIDecryptorClass *klass) @@ -169,6 +345,26 @@ static void gst_cdmidecryptor_class_init( GObjectClass *gobject_class = G_OBJECT_CLASS(klass); GstBaseTransformClass *base_transform_class = GST_BASE_TRANSFORM_CLASS(klass); + /* + * Resolve OCDMGstTransformCaps and discover the platform memory feature + * here in class_init (runs once, before any subclass class_init or + * instance init) so that gst_cdmidecryptor_get_platform_memory_feature() + * and gst_cdmidecryptor_build_src_caps_string() are ready for use by + * subclass class_init implementations (widevine, playready, etc.). + */ + if (!OCDMGstTransformCaps) + { + g_print("surya - Patch applied for gst_cdmidecryptor_class_init\n"); + const char *ocdmgsttransformcaps = "opencdm_gstreamer_transform_caps"; + OCDMGstTransformCaps = (OpenCDMError (*)(GstCaps **))dlsym(RTLD_DEFAULT, ocdmgsttransformcaps); + if (OCDMGstTransformCaps) + GST_INFO("gst_cdmidecryptor_class_init: opencdm_gstreamer_transform_caps resolved"); + else + GST_INFO("gst_cdmidecryptor_class_init: opencdm_gstreamer_transform_caps not found"); + } + gst_cdmidecryptor_discover_platform_memory_feature(); + gst_cdmidecryptor_init_src_mime_types(); + gobject_class->set_property = gst_cdmidecryptor_set_property; gobject_class->dispose = gst_cdmidecryptor_dispose; @@ -209,7 +405,6 @@ static void gst_cdmidecryptor_init( GstCDMIDecryptor *cdmidecryptor) { DEBUG_FUNC(); - const char* ocdmgsttransformcaps = "opencdm_gstreamer_transform_caps"; GstBaseTransform* base = GST_BASE_TRANSFORM(cdmidecryptor); gst_base_transform_set_in_place(base, TRUE); @@ -242,12 +437,12 @@ static void gst_cdmidecryptor_init( cdmidecryptor->sinkCaps = NULL; cdmidecryptor->svpCtx = NULL; - OCDMGstTransformCaps = (OpenCDMError(*)(GstCaps**))dlsym(RTLD_DEFAULT, ocdmgsttransformcaps); - if (OCDMGstTransformCaps) - GST_INFO_OBJECT(cdmidecryptor, "Has opencdm_gstreamer_transform_caps support \n"); - else - GST_INFO_OBJECT(cdmidecryptor, "No opencdm_gstreamer_transform_caps support \n"); - //GST_DEBUG_OBJECT(cdmidecryptor, "******************Init called**********************\n"); + /* OCDMGstTransformCaps, platform memory feature, and srcMimeTypes are + * all resolved once in gst_cdmidecryptor_class_init(). Nothing to do here. */ + g_print("surya - Patch applied for gst_cdmidecryptor_init\n"); + GST_INFO_OBJECT(cdmidecryptor, "cdmidecryptor init: platform memory feature = '%s'", + platformSecureMemFeature ? platformSecureMemFeature : "(not yet discovered)"); + // GST_DEBUG_OBJECT(cdmidecryptor, "******************Init called**********************\n");; } void gst_cdmidecryptor_dispose(GObject * object) @@ -398,7 +593,7 @@ gst_cdmidecryptor_transform_caps(GstBaseTransform * trans, // Check if these caps are present in supported src pad caps in case direction is GST_PAD_SINK, // we can allow caps in this case, since plugin will let the data passthrough gboolean found = false; - for (int j = 0; srcMimeTypes[j]; j++) + for (int j = 0; srcMimeTypes && srcMimeTypes[j]; j++) { if (gst_structure_has_name(in, srcMimeTypes[j])) { @@ -439,12 +634,28 @@ gst_cdmidecryptor_transform_caps(GstBaseTransform * trans, gst_cdmicapsappendifnotduplicate(transformedCaps, out); + g_print("surya - gst_cdmidecryptor_transform_caps: transformedCaps: %" GST_PTR_FORMAT, transformedCaps); if (socInterface && socInterface->IsTransformCapsRequired()) { - if (direction == GST_PAD_SINK && !gst_caps_is_empty(transformedCaps) && OCDMGstTransformCaps) - OCDMGstTransformCaps(&transformedCaps); - } + if (direction == GST_PAD_SINK && !gst_caps_is_empty(transformedCaps)) + { + gchar *caps_before = gst_caps_to_string(transformedCaps); + g_print("surya - gst_cdmidecryptor_transform_caps: transformedCaps before OCDMGstTransformCaps: %s", caps_before); + g_free(caps_before); + if (OCDMGstTransformCaps) + { + OpenCDMError ret = OCDMGstTransformCaps(&transformedCaps); + gchar *caps_after = gst_caps_to_string(transformedCaps); + g_print("surya - gst_cdmidecryptor_transform_caps: transformedCaps after OCDMGstTransformCaps: %s", caps_after); + g_free(caps_after); + } + else + { + GST_WARNING("OCDMGstTransformCaps is NULL - skipping caps transform"); + } + } + } } if (filter) @@ -1147,7 +1358,7 @@ static gboolean gst_cdmidecryptor_accept_caps(GstBaseTransform * trans, for (guint i = 0; i < size; i++) { GstStructure* inCaps = gst_caps_get_structure(caps, i); - for (int j = 0; srcMimeTypes[j]; j++) + for (int j = 0; srcMimeTypes && srcMimeTypes[j]; j++) { if (gst_structure_has_name(inCaps, srcMimeTypes[j])) { diff --git a/gst-plugins/drm/gst/gstcdmidecryptor.h b/gst-plugins/drm/gst/gstcdmidecryptor.h index 2e2cc33d..b71d6216 100644 --- a/gst-plugins/drm/gst/gstcdmidecryptor.h +++ b/gst-plugins/drm/gst/gstcdmidecryptor.h @@ -84,6 +84,30 @@ struct _GstCDMIDecryptorClass */ GType gst_cdmidecryptor_get_type (void); +/** + * @brief Build a dynamic GstCaps string for the src pad template of a decryptor, + * appending the platform-specific secure memory feature (if any) to video types. + * + * The returned string is allocated with g_strdup_printf and must be freed with g_free(). + * Typically called from a subclass class_init to construct a dynamic pad template. + * + * @param platformMemFeature Platform memory feature string (e.g. "memory:MediaTekSecure"), + * or NULL / empty string if no secure memory feature exists. + * @retval Newly allocated caps string suitable for gst_caps_from_string(). + */ +gchar *gst_cdmidecryptor_build_src_caps_string(const gchar *platformMemFeature); + +/** + * @brief Return the platform-specific secure memory feature string discovered at runtime. + * + * The string is owned by the cdmidecryptor module — callers must NOT free it. + * Returns NULL if discovery has not yet run, or an empty string "" if there is + * no platform-specific memory feature on this device. + * + * @retval Platform memory feature (e.g. "memory:MediaTekSecure") or "" or NULL. + */ +const gchar *gst_cdmidecryptor_get_platform_memory_feature(void); + G_END_DECLS #endif diff --git a/gst-plugins/drm/gst/gstplayreadydecryptor.cpp b/gst-plugins/drm/gst/gstplayreadydecryptor.cpp index 392fa16f..c099a6f2 100644 --- a/gst-plugins/drm/gst/gstplayreadydecryptor.cpp +++ b/gst-plugins/drm/gst/gstplayreadydecryptor.cpp @@ -46,10 +46,14 @@ GST_DEBUG_CATEGORY(gst_playreadydecryptor_debug_category); /* pad templates */ -static GstStaticPadTemplate gst_playreadydecryptor_src_template = - GST_STATIC_PAD_TEMPLATE("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS("video/x-h264;video/x-h264(memory:SecMem);audio/mpeg;video/x-h265;video/x-h265(memory:SecMem);audio/x-eac3;audio/x-gst-fourcc-ec_3;audio/x-ac3;audio/x-ac4")); - +/* + * The src pad template caps are built dynamically at class_init time using + * gst_cdmidecryptor_build_src_caps_string() so that platform-specific secure + * memory features (e.g. "memory:MediaTekSecure") are included without + * hardcoding them here. No GST_STATIC_PAD_TEMPLATE / GST_STATIC_CAPS needed + * for the src pad. + */ + static GstStaticPadTemplate gst_playreadydecryptor_sink_template = GST_STATIC_PAD_TEMPLATE("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS( @@ -79,10 +83,27 @@ static void gst_playreadydecryptor_class_init( gobject_class->finalize = gst_playreadydecryptor_finalize; - /* Setting up pads and setting metadata should be moved to - base_class_init if you intend to subclass this class. */ - gst_element_class_add_static_pad_template(elementClass, &gst_playreadydecryptor_src_template); - gst_element_class_add_static_pad_template(elementClass, &gst_playreadydecryptor_sink_template); + /* Build the src pad template dynamically so the correct platform memory + * feature (e.g. "memory:MediaTekSecure" on MTK, "memory:SecMem" on + * Amlogic) is included without any compile-time hardcoding. */ + const gchar *platformMemFeature = gst_cdmidecryptor_get_platform_memory_feature(); + gchar *srcCapsStr = gst_cdmidecryptor_build_src_caps_string(platformMemFeature); + GstCaps *srcCaps = gst_caps_from_string(srcCapsStr); + g_free(srcCapsStr); + g_print("surya - playreadydecryptor: setting dynamic src pad template caps1\n"); + if (srcCaps) + { + GstPadTemplate *srcTemplate = gst_pad_template_new("src", GST_PAD_SRC, GST_PAD_ALWAYS, srcCaps); + gst_caps_unref(srcCaps); + gst_element_class_add_pad_template(elementClass, srcTemplate); + } + else + { + g_print("surya - playreadydecryptor: failed to create dynamic src pad template caps\n"); + } + g_print("surya - playreadydecryptor: setting dynamic src pad template caps2\n"); + + gst_element_class_add_static_pad_template(elementClass, &gst_playreadydecryptor_sink_template); gst_element_class_set_static_metadata(elementClass, "Decrypt PlayReady encrypted contents", diff --git a/gst-plugins/drm/gst/gstwidevinedecryptor.cpp b/gst-plugins/drm/gst/gstwidevinedecryptor.cpp index 99a3f86e..1f7091d7 100644 --- a/gst-plugins/drm/gst/gstwidevinedecryptor.cpp +++ b/gst-plugins/drm/gst/gstwidevinedecryptor.cpp @@ -45,9 +45,13 @@ GST_DEBUG_CATEGORY(gst_widevinedecryptor_debug_category); /* pad templates */ -static GstStaticPadTemplate gst_widevinedecryptor_src_template = - GST_STATIC_PAD_TEMPLATE("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS("video/x-h264;video/x-h264(memory:SecMem);audio/mpeg;video/x-h265;video/x-h265(memory:SecMem);audio/x-eac3;audio/x-gst-fourcc-ec_3;audio/x-ac3;audio/x-opus;audio/x-ac4")); +/* + * The src pad template caps are built dynamically at class_init time using + * gst_cdmidecryptor_build_src_caps_string() so that platform-specific secure + * memory features (e.g. "memory:MediaTekSecure") are included without + * hardcoding them here. No GST_STATIC_PAD_TEMPLATE / GST_STATIC_CAPS needed + * for the src pad. + */ static GstStaticPadTemplate gst_widevinedecryptor_sink_template = GST_STATIC_PAD_TEMPLATE("sink", GST_PAD_SINK, GST_PAD_ALWAYS, @@ -75,10 +79,28 @@ static void gst_widevinedecryptor_class_init(GstwidevinedecryptorClass * klass) gobject_class->finalize = gst_widevinedecryptor_finalize; - /* Setting up pads and setting metadata should be moved to - base_class_init if you intend to subclass this class. */ - gst_element_class_add_static_pad_template(elementClass, &gst_widevinedecryptor_src_template); - gst_element_class_add_static_pad_template(elementClass, &gst_widevinedecryptor_sink_template); + /* Build the src pad template dynamically so the correct platform memory + * feature (e.g. "memory:MediaTekSecure" on MTK, "memory:SecMem" on + * Amlogic) is included without any compile-time hardcoding. + */ + const gchar *platformMemFeature = gst_cdmidecryptor_get_platform_memory_feature(); + gchar *srcCapsStr = gst_cdmidecryptor_build_src_caps_string(platformMemFeature); + GstCaps *srcCaps = gst_caps_from_string(srcCapsStr); + g_free(srcCapsStr); + g_print("surya - widevinedecryptor: setting dynamic src pad template caps1\n"); + if (srcCaps) + { + GstPadTemplate *srcTemplate = gst_pad_template_new("src", GST_PAD_SRC, GST_PAD_ALWAYS, srcCaps); + gst_caps_unref(srcCaps); + gst_element_class_add_pad_template(elementClass, srcTemplate); + } + else + { + g_print("surya - widevinedecryptor: failed to create dynamic src pad template caps\n"); + } + g_print("surya - widevinedecryptor: setting dynamic src pad template caps2\n"); + + gst_element_class_add_static_pad_template(elementClass, &gst_widevinedecryptor_sink_template); gst_element_class_set_static_metadata(elementClass, "Decrypt Widevine encrypted contents",