[GStreamer][MiniBrowser] Honor GStreamer command line parameters in MiniBrowser
[WebKit-https.git] / Source / WebCore / platform / graphics / gstreamer / GStreamerUtilities.cpp
index 7706752..ea20229 100644 (file)
 #include "GStreamerUtilities.h"
 
 #include "GRefPtrGStreamer.h"
+#include "GstAllocatorFastMalloc.h"
 #include "IntSize.h"
 
 #include <gst/audio/audio-info.h>
 #include <gst/gst.h>
-#include <wtf/MathExtras.h>
 #include <wtf/glib/GUniquePtr.h>
 
 #if ENABLE(VIDEO_TRACK) && USE(GSTREAMER_MPEGTS)
@@ -59,22 +59,72 @@ GstPad* webkitGstGhostPadFromStaticTemplate(GstStaticPadTemplate* staticPadTempl
 #if ENABLE(VIDEO)
 bool getVideoSizeAndFormatFromCaps(GstCaps* caps, WebCore::IntSize& size, GstVideoFormat& format, int& pixelAspectRatioNumerator, int& pixelAspectRatioDenominator, int& stride)
 {
-    GstVideoInfo info;
-
-    gst_video_info_init(&info);
-    if (!gst_video_info_from_caps(&info, caps))
+    if (!doCapsHaveType(caps, GST_VIDEO_CAPS_TYPE_PREFIX)) {
+        GST_WARNING("Failed to get the video size and format, these are not a video caps");
         return false;
+    }
+
+    if (areEncryptedCaps(caps)) {
+        GstStructure* structure = gst_caps_get_structure(caps, 0);
+        format = GST_VIDEO_FORMAT_ENCODED;
+        stride = 0;
+        int width = 0, height = 0;
+        gst_structure_get_int(structure, "width", &width);
+        gst_structure_get_int(structure, "height", &height);
+        if (!gst_structure_get_fraction(structure, "pixel-aspect-ratio", &pixelAspectRatioNumerator, &pixelAspectRatioDenominator)) {
+            pixelAspectRatioNumerator = 1;
+            pixelAspectRatioDenominator = 1;
+        }
 
-    format = GST_VIDEO_INFO_FORMAT(&info);
-    size.setWidth(GST_VIDEO_INFO_WIDTH(&info));
-    size.setHeight(GST_VIDEO_INFO_HEIGHT(&info));
-    pixelAspectRatioNumerator = GST_VIDEO_INFO_PAR_N(&info);
-    pixelAspectRatioDenominator = GST_VIDEO_INFO_PAR_D(&info);
-    stride = GST_VIDEO_INFO_PLANE_STRIDE(&info, 0);
+        size.setWidth(width);
+        size.setHeight(height);
+    } else {
+        GstVideoInfo info;
+        gst_video_info_init(&info);
+        if (!gst_video_info_from_caps(&info, caps))
+            return false;
+
+        format = GST_VIDEO_INFO_FORMAT(&info);
+        size.setWidth(GST_VIDEO_INFO_WIDTH(&info));
+        size.setHeight(GST_VIDEO_INFO_HEIGHT(&info));
+        pixelAspectRatioNumerator = GST_VIDEO_INFO_PAR_N(&info);
+        pixelAspectRatioDenominator = GST_VIDEO_INFO_PAR_D(&info);
+        stride = GST_VIDEO_INFO_PLANE_STRIDE(&info, 0);
+    }
 
     return true;
 }
 
+std::optional<FloatSize> getVideoResolutionFromCaps(const GstCaps* caps)
+{
+    if (!doCapsHaveType(caps, GST_VIDEO_CAPS_TYPE_PREFIX)) {
+        GST_WARNING("Failed to get the video resolution, these are not a video caps");
+        return std::nullopt;
+    }
+
+    int width = 0, height = 0;
+    int pixelAspectRatioNumerator = 1, pixelAspectRatioDenominator = 1;
+
+    if (areEncryptedCaps(caps)) {
+        GstStructure* structure = gst_caps_get_structure(caps, 0);
+        gst_structure_get_int(structure, "width", &width);
+        gst_structure_get_int(structure, "height", &height);
+        gst_structure_get_fraction(structure, "pixel-aspect-ratio", &pixelAspectRatioNumerator, &pixelAspectRatioDenominator);
+    } else {
+        GstVideoInfo info;
+        gst_video_info_init(&info);
+        if (!gst_video_info_from_caps(&info, caps))
+            return std::nullopt;
+
+        width = GST_VIDEO_INFO_WIDTH(&info);
+        height = GST_VIDEO_INFO_HEIGHT(&info);
+        pixelAspectRatioNumerator = GST_VIDEO_INFO_PAR_N(&info);
+        pixelAspectRatioDenominator = GST_VIDEO_INFO_PAR_D(&info);
+    }
+
+    return std::make_optional(FloatSize(width, height * (static_cast<float>(pixelAspectRatioNumerator) / static_cast<float>(pixelAspectRatioDenominator))));
+}
+
 bool getSampleVideoInfo(GstSample* sample, GstVideoInfo& videoInfo)
 {
     if (!GST_IS_SAMPLE(sample))
@@ -113,6 +163,47 @@ GstBuffer* createGstBufferForData(const char* data, int length)
     return buffer;
 }
 
+const char* capsMediaType(const GstCaps* caps)
+{
+    ASSERT(caps);
+    GstStructure* structure = gst_caps_get_structure(caps, 0);
+    if (!structure) {
+        GST_WARNING("caps are empty");
+        return nullptr;
+    }
+#if ENABLE(ENCRYPTED_MEDIA)
+    if (gst_structure_has_name(structure, "application/x-cenc"))
+        return gst_structure_get_string(structure, "original-media-type");
+#endif
+    return gst_structure_get_name(structure);
+}
+
+bool doCapsHaveType(const GstCaps* caps, const char* type)
+{
+    const char* mediaType = capsMediaType(caps);
+    if (!mediaType) {
+        GST_WARNING("Failed to get MediaType");
+        return false;
+    }
+    return g_str_has_prefix(mediaType, type);
+}
+
+bool areEncryptedCaps(const GstCaps* caps)
+{
+    ASSERT(caps);
+#if ENABLE(ENCRYPTED_MEDIA)
+    GstStructure* structure = gst_caps_get_structure(caps, 0);
+    if (!structure) {
+        GST_WARNING("caps are empty");
+        return false;
+    }
+    return gst_structure_has_name(structure, "application/x-cenc");
+#else
+    UNUSED_PARAM(caps);
+    return false;
+#endif
+}
+
 char* getGstBufferDataPointer(GstBuffer* buffer)
 {
     GstMiniObject* miniObject = reinterpret_cast<GstMiniObject*>(buffer);
@@ -145,22 +236,35 @@ void unmapGstBuffer(GstBuffer* buffer)
     fastFree(mapInfo);
 }
 
-bool initializeGStreamer()
+bool initializeGStreamer(Vector<String>& parameters)
 {
-    if (gst_is_initialized())
-        return true;
-
     GUniqueOutPtr<GError> error;
-    // FIXME: We should probably pass the arguments from the command line.
-    bool gstInitialized = gst_init_check(nullptr, nullptr, &error.outPtr());
-    ASSERT_WITH_MESSAGE(gstInitialized, "GStreamer initialization failed: %s", error ? error->message : "unknown error occurred");
+    bool isGStreamerInitialized = false;
+
+#if ENABLE(VIDEO) || ENABLE(WEB_AUDIO)
+    char** argv = g_new0(char*, parameters.size() + 2);
+    argv[0] = g_strdup("WebProcess");
+    for (unsigned i = 1; i < parameters.size(); i++)
+        argv[i] = g_strdup(parameters[i].utf8().data());
+
+    int size = g_strv_length(argv);
+    isGStreamerInitialized = gst_init_check(&size, &argv, &error.outPtr());
+    g_strfreev(argv);
+    ASSERT_WITH_MESSAGE(isGStreamerInitialized, "GStreamer initialization failed: %s", error ? error->message : "unknown error occurred");
+
+    if (isFastMallocEnabled()) {
+        const char* disableFastMalloc = getenv("WEBKIT_GST_DISABLE_FAST_MALLOC");
+        if (!disableFastMalloc || !strcmp(disableFastMalloc, "0"))
+            gst_allocator_set_default(GST_ALLOCATOR(g_object_new(gst_allocator_fast_malloc_get_type(), nullptr)));
+    }
 
 #if ENABLE(VIDEO_TRACK) && USE(GSTREAMER_MPEGTS)
-    if (gstInitialized)
+    if (isGStreamerInitialized)
         gst_mpegts_initialize();
 #endif
+#endif
 
-    return gstInitialized;
+    return isGStreamerInitialized;
 }
 
 unsigned getGstPlayFlag(const char* nick)
@@ -175,16 +279,15 @@ unsigned getGstPlayFlag(const char* nick)
     return flag->value;
 }
 
-GstClockTime toGstClockTime(float time)
+// Convert a MediaTime in seconds to a GstClockTime. Note that we can get MediaTime objects with a time scale that isn't a GST_SECOND, since they can come to
+// us through the internal testing API, the DOM and internally. It would be nice to assert the format of the incoming time, but all the media APIs assume time
+// is passed around in fractional seconds, so we'll just have to assume the same.
+uint64_t toGstUnsigned64Time(const MediaTime& mediaTime)
 {
-    // Extract the integer part of the time (seconds) and the fractional part (microseconds). Attempt to
-    // round the microseconds so no floating point precision is lost and we can perform an accurate seek.
-    float seconds;
-    float microSeconds = modff(time, &seconds) * 1000000;
-    GTimeVal timeValue;
-    timeValue.tv_sec = static_cast<glong>(seconds);
-    timeValue.tv_usec = static_cast<glong>(floor(microSeconds + 0.5));
-    return GST_TIMEVAL_TO_TIME(timeValue);
+    MediaTime time = mediaTime.toTimeScale(GST_SECOND);
+    if (time.isInvalid())
+        return GST_CLOCK_TIME_NONE;
+    return time.timeValue();
 }
 
 bool gstRegistryHasElementForMediaType(GList* elementFactories, const char* capsString)
@@ -197,46 +300,6 @@ bool gstRegistryHasElementForMediaType(GList* elementFactories, const char* caps
     return result;
 }
 
-#if GST_CHECK_VERSION(1, 5, 3) && (ENABLE(LEGACY_ENCRYPTED_MEDIA) || ENABLE(ENCRYPTED_MEDIA))
-GstElement* createGstDecryptor(const gchar* protectionSystem)
-{
-    GstElement* decryptor = nullptr;
-    GList* decryptors = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_DECRYPTOR, GST_RANK_MARGINAL);
-
-    GST_TRACE("looking for decryptor for %s", protectionSystem);
-
-    for (GList* walk = decryptors; !decryptor && walk; walk = g_list_next(walk)) {
-        GstElementFactory* factory = reinterpret_cast<GstElementFactory*>(walk->data);
-
-        GST_TRACE("checking factory %s", GST_OBJECT_NAME(factory));
-
-        for (const GList* current = gst_element_factory_get_static_pad_templates(factory); current && !decryptor; current = g_list_next(current)) {
-            GstStaticPadTemplate* staticPadTemplate = static_cast<GstStaticPadTemplate*>(current->data);
-            GRefPtr<GstCaps> caps = adoptGRef(gst_static_pad_template_get_caps(staticPadTemplate));
-            unsigned length = gst_caps_get_size(caps.get());
-
-            GST_TRACE("factory %s caps has size %u", GST_OBJECT_NAME(factory), length);
-            for (unsigned i = 0; !decryptor && i < length; ++i) {
-                GstStructure* structure = gst_caps_get_structure(caps.get(), i);
-                GST_TRACE("checking structure %s", gst_structure_get_name(structure));
-                if (gst_structure_has_field_typed(structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING)) {
-                    const gchar* sysId = gst_structure_get_string(structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD);
-                    GST_TRACE("structure %s has protection system %s", gst_structure_get_name(structure), sysId);
-                    if (!g_ascii_strcasecmp(protectionSystem, sysId)) {
-                        GST_DEBUG("found decryptor %s for %s", GST_OBJECT_NAME(factory), protectionSystem);
-                        decryptor = gst_element_factory_create(factory, nullptr);
-                        break;
-                    }
-                }
-            }
-        }
-    }
-    gst_plugin_feature_list_free(decryptors);
-    GST_TRACE("returning decryptor %p", decryptor);
-    return decryptor;
-}
-#endif
-
 }
 
 #endif // USE(GSTREAMER)