[EME][GStreamer] Add support for encrypted caps in GStreamerUtilities
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 9 Feb 2018 12:11:10 +0000 (12:11 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 9 Feb 2018 12:11:10 +0000 (12:11 +0000)
https://bugs.webkit.org/show_bug.cgi?id=181990

Patch by Yacine Bandou <yacine.bandou_ext@softathome.com> on 2018-02-09
Reviewed by Xabier Rodriguez-Calvar.

Add the support of encrypted caps in GStreamerUtilities.
Refactor the manner that the caps are handled, such as how to extract the resolution
from the video caps or how to check if the caps are encrypted.

The attachTrack function in PlaybackPipeline doesn't need the "structure" parameter,
it is already included in the "caps" parameter.

Replace the "mediaType" parameter by the "caps" parameter in reattachTrack function,
it allows to use the new functions that handle the caps in GStreamerUtilities.

Tests:
    media/encrypted-media/clearKey/clearKey-cenc-audio-playback-mse.html
    media/encrypted-media/clearKey/clearKey-cenc-video-playback-mse.html

* platform/graphics/gstreamer/GStreamerUtilities.cpp:
(WebCore::getVideoSizeAndFormatFromCaps): Add the support of video encrypted caps.
(WebCore::getVideoResolutionFromCaps):
(WebCore::capsMediaType):
(WebCore::doCapsHaveType):
(WebCore::areEncryptedCaps): Add a new functions in order to handle the caps properly.
* platform/graphics/gstreamer/GStreamerUtilities.h:
* platform/graphics/gstreamer/mse/AppendPipeline.cpp:
(WebCore::AppendPipeline::parseDemuxerSrcPadCaps):
* platform/graphics/gstreamer/mse/GStreamerMediaDescription.cpp:
(WebCore::GStreamerMediaDescription::codec const):
(WebCore::GStreamerMediaDescription::isVideo const):
(WebCore::GStreamerMediaDescription::isAudio const):
* platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp:
(WebCore::MediaPlayerPrivateGStreamerMSE::trackDetected):
* platform/graphics/gstreamer/mse/PlaybackPipeline.cpp:
(WebCore::PlaybackPipeline::attachTrack):
(WebCore::PlaybackPipeline::reattachTrack):
* platform/graphics/gstreamer/mse/PlaybackPipeline.h:
* platform/graphics/gstreamer/mse/WebKitMediaSourceGStreamer.cpp:
(webKitMediaSrcUpdatePresentationSize): Refactor some parts by using the new added functions.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@228316 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/gstreamer/GStreamerUtilities.cpp
Source/WebCore/platform/graphics/gstreamer/GStreamerUtilities.h
Source/WebCore/platform/graphics/gstreamer/mse/AppendPipeline.cpp
Source/WebCore/platform/graphics/gstreamer/mse/GStreamerMediaDescription.cpp
Source/WebCore/platform/graphics/gstreamer/mse/GStreamerMediaDescription.h
Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp
Source/WebCore/platform/graphics/gstreamer/mse/PlaybackPipeline.cpp
Source/WebCore/platform/graphics/gstreamer/mse/PlaybackPipeline.h
Source/WebCore/platform/graphics/gstreamer/mse/WebKitMediaSourceGStreamer.cpp

index 24e4702..785a994 100644 (file)
@@ -1,3 +1,46 @@
+2018-02-09  Yacine Bandou  <yacine.bandou_ext@softathome.com>
+
+        [EME][GStreamer] Add support for encrypted caps in GStreamerUtilities
+        https://bugs.webkit.org/show_bug.cgi?id=181990
+
+        Reviewed by Xabier Rodriguez-Calvar.
+
+        Add the support of encrypted caps in GStreamerUtilities.
+        Refactor the manner that the caps are handled, such as how to extract the resolution
+        from the video caps or how to check if the caps are encrypted.
+
+        The attachTrack function in PlaybackPipeline doesn't need the "structure" parameter,
+        it is already included in the "caps" parameter.
+
+        Replace the "mediaType" parameter by the "caps" parameter in reattachTrack function,
+        it allows to use the new functions that handle the caps in GStreamerUtilities.
+
+        Tests:
+            media/encrypted-media/clearKey/clearKey-cenc-audio-playback-mse.html
+            media/encrypted-media/clearKey/clearKey-cenc-video-playback-mse.html
+
+        * platform/graphics/gstreamer/GStreamerUtilities.cpp:
+        (WebCore::getVideoSizeAndFormatFromCaps): Add the support of video encrypted caps.
+        (WebCore::getVideoResolutionFromCaps):
+        (WebCore::capsMediaType):
+        (WebCore::doCapsHaveType):
+        (WebCore::areEncryptedCaps): Add a new functions in order to handle the caps properly.
+        * platform/graphics/gstreamer/GStreamerUtilities.h:
+        * platform/graphics/gstreamer/mse/AppendPipeline.cpp:
+        (WebCore::AppendPipeline::parseDemuxerSrcPadCaps):
+        * platform/graphics/gstreamer/mse/GStreamerMediaDescription.cpp:
+        (WebCore::GStreamerMediaDescription::codec const):
+        (WebCore::GStreamerMediaDescription::isVideo const):
+        (WebCore::GStreamerMediaDescription::isAudio const):
+        * platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp:
+        (WebCore::MediaPlayerPrivateGStreamerMSE::trackDetected):
+        * platform/graphics/gstreamer/mse/PlaybackPipeline.cpp:
+        (WebCore::PlaybackPipeline::attachTrack):
+        (WebCore::PlaybackPipeline::reattachTrack):
+        * platform/graphics/gstreamer/mse/PlaybackPipeline.h:
+        * platform/graphics/gstreamer/mse/WebKitMediaSourceGStreamer.cpp:
+        (webKitMediaSrcUpdatePresentationSize): Refactor some parts by using the new added functions.
+
 2018-02-09  Philippe Normand  <pnormand@igalia.com>
 
         [GStreamer] Layout test fast/replaced/border-radius-clip.html crashes with GStreamer-CRITICAL **: gst_segment_to_stream_time: assertion 'segment->format == format' failed in gst_segment_to_stream_time()
index 4762ae8..8c2e0c2 100644 (file)
@@ -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;
+    }
 
-    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);
+    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;
+        }
+
+        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);
index e168582..8472d78 100644 (file)
@@ -20,6 +20,7 @@
 #pragma once
 
 
+#include "FloatSize.h"
 #include <gst/gst.h>
 #include <gst/video/video-format.h>
 #include <gst/video/video-info.h>
@@ -50,14 +51,22 @@ inline bool webkitGstCheckVersion(guint major, guint minor, guint micro)
     return true;
 }
 
+#define GST_VIDEO_CAPS_TYPE_PREFIX  "video/"
+#define GST_AUDIO_CAPS_TYPE_PREFIX  "audio/"
+#define GST_TEXT_CAPS_TYPE_PREFIX   "text/"
+
 GstPad* webkitGstGhostPadFromStaticTemplate(GstStaticPadTemplate*, const gchar* name, GstPad* target);
 #if ENABLE(VIDEO)
 bool getVideoSizeAndFormatFromCaps(GstCaps*, WebCore::IntSize&, GstVideoFormat&, int& pixelAspectRatioNumerator, int& pixelAspectRatioDenominator, int& stride);
+std::optional<FloatSize> getVideoResolutionFromCaps(const GstCaps*);
 bool getSampleVideoInfo(GstSample*, GstVideoInfo&);
 #endif
 GstBuffer* createGstBuffer(GstBuffer*);
 GstBuffer* createGstBufferForData(const char* data, int length);
 char* getGstBufferDataPointer(GstBuffer*);
+const char* capsMediaType(const GstCaps*);
+bool doCapsHaveType(const GstCaps*, const char*);
+bool areEncryptedCaps(const GstCaps*);
 void mapGstBuffer(GstBuffer*, uint32_t);
 void unmapGstBuffer(GstBuffer*);
 bool initializeGStreamer();
index cebbf2e..a53009b 100644 (file)
@@ -27,6 +27,7 @@
 #include "GRefPtrGStreamer.h"
 #include "GStreamerEMEUtilities.h"
 #include "GStreamerMediaDescription.h"
+#include "GStreamerUtilities.h"
 #include "MediaSampleGStreamer.h"
 #include "InbandTextTrackPrivateGStreamer.h"
 #include "MediaDescription.h"
@@ -582,74 +583,36 @@ void AppendPipeline::parseDemuxerSrcPadCaps(GstCaps* demuxerSrcPadCaps)
 
     m_demuxerSrcPadCaps = adoptGRef(demuxerSrcPadCaps);
     m_streamType = WebCore::MediaSourceStreamTypeGStreamer::Unknown;
-
-    GstStructure* structure = gst_caps_get_structure(m_demuxerSrcPadCaps.get(), 0);
-    bool sizeConfigured = false;
-
-#if GST_CHECK_VERSION(1, 5, 3) && ENABLE(ENCRYPTED_MEDIA)
-    if (gst_structure_has_name(structure, "application/x-cenc")) {
+#if ENABLE(ENCRYPTED_MEDIA)
+    if (areEncryptedCaps(m_demuxerSrcPadCaps.get())) {
         // Any previous decryptor should have been removed from the pipeline by disconnectFromAppSinkFromStreamingThread()
         ASSERT(!m_decryptor);
-
+        GstStructure* structure = gst_caps_get_structure(m_demuxerSrcPadCaps.get(), 0);
         m_decryptor = GStreamerEMEUtilities::createDecryptor(gst_structure_get_string(structure, "protection-system"));
         if (!m_decryptor) {
             GST_ERROR("decryptor not found for caps: %" GST_PTR_FORMAT, m_demuxerSrcPadCaps.get());
             return;
         }
-
-        const gchar* originalMediaType = gst_structure_get_string(structure, "original-media-type");
-
-        if (!MediaPlayerPrivateGStreamerMSE::supportsCodec(originalMediaType)) {
-            m_presentationSize = WebCore::FloatSize();
-            m_streamType = WebCore::MediaSourceStreamTypeGStreamer::Invalid;
-        } else if (g_str_has_prefix(originalMediaType, "video/")) {
-            int width = 0;
-            int height = 0;
-            float finalHeight = 0;
-
-            if (gst_structure_get_int(structure, "width", &width) && gst_structure_get_int(structure, "height", &height)) {
-                int ratioNumerator = 1;
-                int ratioDenominator = 1;
-
-                gst_structure_get_fraction(structure, "pixel-aspect-ratio", &ratioNumerator, &ratioDenominator);
-                finalHeight = height * ((float) ratioDenominator / (float) ratioNumerator);
-            }
-
-            m_presentationSize = WebCore::FloatSize(width, finalHeight);
-            m_streamType = WebCore::MediaSourceStreamTypeGStreamer::Video;
-        } else {
-            m_presentationSize = WebCore::FloatSize();
-            if (g_str_has_prefix(originalMediaType, "audio/"))
-                m_streamType = WebCore::MediaSourceStreamTypeGStreamer::Audio;
-            else if (g_str_has_prefix(originalMediaType, "text/"))
-                m_streamType = WebCore::MediaSourceStreamTypeGStreamer::Text;
-        }
-        sizeConfigured = true;
     }
 #endif
-
-    if (!sizeConfigured) {
-        const char* structureName = gst_structure_get_name(structure);
-        GstVideoInfo info;
-
-        if (!MediaPlayerPrivateGStreamerMSE::supportsCodec(structureName)) {
+    const char* originalMediaType = capsMediaType(m_demuxerSrcPadCaps.get());
+    if (!MediaPlayerPrivateGStreamerMSE::supportsCodec(originalMediaType)) {
             m_presentationSize = WebCore::FloatSize();
             m_streamType = WebCore::MediaSourceStreamTypeGStreamer::Invalid;
-        } else if (g_str_has_prefix(structureName, "video/") && gst_video_info_from_caps(&info, demuxerSrcPadCaps)) {
-            float width, height;
-
-            width = info.width;
-            height = info.height * ((float) info.par_d / (float) info.par_n);
-
-            m_presentationSize = WebCore::FloatSize(width, height);
-            m_streamType = WebCore::MediaSourceStreamTypeGStreamer::Video;
-        } else {
+    } else if (doCapsHaveType(m_demuxerSrcPadCaps.get(), GST_VIDEO_CAPS_TYPE_PREFIX)) {
+        std::optional<FloatSize> size = getVideoResolutionFromCaps(m_demuxerSrcPadCaps.get());
+        if (size.has_value())
+            m_presentationSize = size.value();
+        else
             m_presentationSize = WebCore::FloatSize();
-            if (g_str_has_prefix(structureName, "audio/"))
-                m_streamType = WebCore::MediaSourceStreamTypeGStreamer::Audio;
-            else if (g_str_has_prefix(structureName, "text/"))
-                m_streamType = WebCore::MediaSourceStreamTypeGStreamer::Text;
-        }
+
+        m_streamType = WebCore::MediaSourceStreamTypeGStreamer::Video;
+    } else {
+        m_presentationSize = WebCore::FloatSize();
+        if (doCapsHaveType(m_demuxerSrcPadCaps.get(), GST_AUDIO_CAPS_TYPE_PREFIX))
+            m_streamType = WebCore::MediaSourceStreamTypeGStreamer::Audio;
+        else if (doCapsHaveType(m_demuxerSrcPadCaps.get(), GST_TEXT_CAPS_TYPE_PREFIX))
+            m_streamType = WebCore::MediaSourceStreamTypeGStreamer::Text;
     }
 }
 
index 776a0be..9c8d624 100644 (file)
@@ -20,7 +20,7 @@
 
 #include "config.h"
 #include "GStreamerMediaDescription.h"
-
+#include "GStreamerUtilities.h"
 #include "GUniquePtrGStreamer.h"
 
 #include <gst/pbutils/pbutils.h>
@@ -33,35 +33,17 @@ namespace WebCore {
 
 AtomicString GStreamerMediaDescription::codec() const
 {
-    GUniquePtr<gchar> description(gst_pb_utils_get_codec_description(m_caps.get()));
-    String codecName(description.get());
-
-    // Report "H.264 (Main Profile)" and "H.264 (High Profile)" just as "H.264" to allow changes between both variants
-    // go unnoticed to the SourceBuffer layer.
-    if (codecName.startsWith("H.264")) {
-        size_t braceStart = codecName.find(" (");
-        size_t braceEnd = codecName.find(")");
-        if (braceStart != notFound && braceEnd != notFound)
-            codecName.remove(braceStart, braceEnd-braceStart);
-    }
-
-    return codecName;
+    return m_codecName;
 }
 
 bool GStreamerMediaDescription::isVideo() const
 {
-    GstStructure* structure = gst_caps_get_structure(m_caps.get(), 0);
-    const gchar* name = gst_structure_get_name(structure);
-
-    return g_str_has_prefix(name, "video/");
+    return doCapsHaveType(m_caps.get(), GST_VIDEO_CAPS_TYPE_PREFIX);
 }
 
 bool GStreamerMediaDescription::isAudio() const
 {
-    GstStructure* structure = gst_caps_get_structure(m_caps.get(), 0);
-    const gchar* name = gst_structure_get_name(structure);
-
-    return g_str_has_prefix(name, "audio/");
+    return doCapsHaveType(m_caps.get(), GST_AUDIO_CAPS_TYPE_PREFIX);
 }
 
 bool GStreamerMediaDescription::isText() const
@@ -70,6 +52,43 @@ bool GStreamerMediaDescription::isText() const
     return false;
 }
 
+AtomicString GStreamerMediaDescription::extractCodecName()
+{
+    GRefPtr<GstCaps> originalCaps = m_caps;
+
+    if (areEncryptedCaps(originalCaps.get())) {
+        originalCaps = adoptGRef(gst_caps_copy(originalCaps.get()));
+        GstStructure* structure = gst_caps_get_structure(originalCaps.get(), 0);
+
+        if (!gst_structure_has_field(structure, "original-media-type"))
+            return AtomicString();
+
+        gst_structure_set_name(structure, gst_structure_get_string(structure, "original-media-type"));
+        // Remove the DRM related fields from the caps.
+        for (int j = 0; j < gst_structure_n_fields(structure); ++j) {
+            const char* fieldName = gst_structure_nth_field_name(structure, j);
+
+            if (g_str_has_prefix(fieldName, "protection-system")
+                || g_str_has_prefix(fieldName, "original-media-type"))
+                gst_structure_remove_field(structure, fieldName);
+        }
+    }
+
+    GUniquePtr<gchar> description(gst_pb_utils_get_codec_description(originalCaps.get()));
+    String codecName(description.get());
+
+    // Report "H.264 (Main Profile)" and "H.264 (High Profile)" just as "H.264" to allow changes between both variants
+    // go unnoticed to the SourceBuffer layer.
+    if (codecName.startsWith("H.264")) {
+        size_t braceStart = codecName.find(" (");
+        size_t braceEnd = codecName.find(")");
+        if (braceStart != notFound && braceEnd != notFound)
+            codecName.remove(braceStart, braceEnd - braceStart);
+    }
+
+    return codecName;
+}
+
 } // namespace WebCore.
 
 #endif // USE(GSTREAMER)
index 84e263c..635ebc7 100644 (file)
@@ -26,6 +26,7 @@
 #include "MediaDescription.h"
 
 #include <gst/gst.h>
+#include <wtf/text/AtomicString.h>
 
 namespace WebCore {
 
@@ -48,9 +49,12 @@ private:
         : MediaDescription()
         , m_caps(caps)
     {
+        m_codecName = extractCodecName();
     }
 
+    AtomicString extractCodecName();
     GRefPtr<GstCaps> m_caps;
+    AtomicString m_codecName;
 };
 
 } // namespace WebCore.
index e07ec59..918c427 100644 (file)
@@ -739,23 +739,16 @@ void MediaPlayerPrivateGStreamerMSE::trackDetected(RefPtr<AppendPipeline> append
     ASSERT(caps);
     GST_DEBUG("track ID: %s, caps: %" GST_PTR_FORMAT, newTrack->id().string().latin1().data(), caps);
 
-    GstStructure* structure = gst_caps_get_structure(caps, 0);
-    const gchar* mediaType = gst_structure_get_name(structure);
-    GstVideoInfo info;
-
-    if (g_str_has_prefix(mediaType, "video/") && gst_video_info_from_caps(&info, caps)) {
-        float width, height;
-
-        width = info.width;
-        height = info.height * ((float) info.par_d / (float) info.par_n);
-        m_videoSize.setWidth(width);
-        m_videoSize.setHeight(height);
+    if (doCapsHaveType(caps, GST_VIDEO_CAPS_TYPE_PREFIX)) {
+        std::optional<FloatSize> size = getVideoResolutionFromCaps(caps);
+        if (size.has_value())
+            m_videoSize = size.value();
     }
 
     if (firstTrackDetected)
-        m_playbackPipeline->attachTrack(appendPipeline->sourceBufferPrivate(), newTrack, structure, caps);
+        m_playbackPipeline->attachTrack(appendPipeline->sourceBufferPrivate(), newTrack, caps);
     else
-        m_playbackPipeline->reattachTrack(appendPipeline->sourceBufferPrivate(), newTrack, mediaType);
+        m_playbackPipeline->reattachTrack(appendPipeline->sourceBufferPrivate(), newTrack, caps);
 }
 
 const static HashSet<AtomicString>& codecSet()
index 53199f6..73d3261 100644 (file)
@@ -162,7 +162,7 @@ void PlaybackPipeline::removeSourceBuffer(RefPtr<SourceBufferPrivateGStreamer> s
         webKitMediaSrcFreeStream(m_webKitMediaSrc.get(), stream);
 }
 
-void PlaybackPipeline::attachTrack(RefPtr<SourceBufferPrivateGStreamer> sourceBufferPrivate, RefPtr<TrackPrivateBase> trackPrivate, GstStructure* structure, GstCaps* caps)
+void PlaybackPipeline::attachTrack(RefPtr<SourceBufferPrivateGStreamer> sourceBufferPrivate, RefPtr<TrackPrivateBase> trackPrivate, GstCaps* caps)
 {
     WebKitMediaSrc* webKitMediaSrc = m_webKitMediaSrc.get();
 
@@ -177,8 +177,7 @@ void PlaybackPipeline::attachTrack(RefPtr<SourceBufferPrivateGStreamer> sourceBu
     stream->parent->priv->numberOfPads++;
     GST_OBJECT_UNLOCK(webKitMediaSrc);
 
-    const gchar* mediaType = gst_structure_get_name(structure);
-
+    const char* mediaType = capsMediaType(caps);
     GST_DEBUG_OBJECT(webKitMediaSrc, "Configured track %s: appsrc=%s, padId=%u, mediaType=%s", trackPrivate->id().string().utf8().data(), GST_ELEMENT_NAME(stream->appsrc), padId, mediaType);
 
     GUniquePtr<gchar> parserBinName(g_strdup_printf("streamparser%u", padId));
@@ -217,6 +216,7 @@ void PlaybackPipeline::attachTrack(RefPtr<SourceBufferPrivateGStreamer> sourceBu
         gst_element_add_pad(stream->parser, gst_ghost_pad_new("src", pad.get()));
     } else if (!g_strcmp0(mediaType, "audio/mpeg")) {
         gint mpegversion = -1;
+        GstStructure* structure = gst_caps_get_structure(caps, 0);
         gst_structure_get_int(structure, "mpegversion", &mpegversion);
 
         GstElement* parser = nullptr;
@@ -272,17 +272,17 @@ void PlaybackPipeline::attachTrack(RefPtr<SourceBufferPrivateGStreamer> sourceBu
     int signal = -1;
 
     GST_OBJECT_LOCK(webKitMediaSrc);
-    if (g_str_has_prefix(mediaType, "audio")) {
+    if (doCapsHaveType(caps, GST_AUDIO_CAPS_TYPE_PREFIX)) {
         stream->type = Audio;
         stream->parent->priv->numberOfAudioStreams++;
         signal = SIGNAL_AUDIO_CHANGED;
         stream->audioTrack = RefPtr<WebCore::AudioTrackPrivateGStreamer>(static_cast<WebCore::AudioTrackPrivateGStreamer*>(trackPrivate.get()));
-    } else if (g_str_has_prefix(mediaType, "video")) {
+    } else if (doCapsHaveType(caps, GST_VIDEO_CAPS_TYPE_PREFIX)) {
         stream->type = Video;
         stream->parent->priv->numberOfVideoStreams++;
         signal = SIGNAL_VIDEO_CHANGED;
         stream->videoTrack = RefPtr<WebCore::VideoTrackPrivateGStreamer>(static_cast<WebCore::VideoTrackPrivateGStreamer*>(trackPrivate.get()));
-    } else if (g_str_has_prefix(mediaType, "text")) {
+    } else if (doCapsHaveType(caps, GST_TEXT_CAPS_TYPE_PREFIX)) {
         stream->type = Text;
         stream->parent->priv->numberOfTextStreams++;
         signal = SIGNAL_TEXT_CHANGED;
@@ -295,7 +295,7 @@ void PlaybackPipeline::attachTrack(RefPtr<SourceBufferPrivateGStreamer> sourceBu
         g_signal_emit(G_OBJECT(stream->parent), webKitMediaSrcSignals[signal], 0, nullptr);
 }
 
-void PlaybackPipeline::reattachTrack(RefPtr<SourceBufferPrivateGStreamer> sourceBufferPrivate, RefPtr<TrackPrivateBase> trackPrivate, const char* mediaType)
+void PlaybackPipeline::reattachTrack(RefPtr<SourceBufferPrivateGStreamer> sourceBufferPrivate, RefPtr<TrackPrivateBase> trackPrivate, GstCaps* caps)
 {
     GST_DEBUG("Re-attaching track");
 
@@ -313,15 +313,15 @@ void PlaybackPipeline::reattachTrack(RefPtr<SourceBufferPrivateGStreamer> source
     int signal = -1;
 
     GST_OBJECT_LOCK(webKitMediaSrc);
-    if (g_str_has_prefix(mediaType, "audio")) {
+    if (doCapsHaveType(caps, GST_AUDIO_CAPS_TYPE_PREFIX)) {
         ASSERT(stream->type == Audio);
         signal = SIGNAL_AUDIO_CHANGED;
         stream->audioTrack = RefPtr<WebCore::AudioTrackPrivateGStreamer>(static_cast<WebCore::AudioTrackPrivateGStreamer*>(trackPrivate.get()));
-    } else if (g_str_has_prefix(mediaType, "video")) {
+    } else if (doCapsHaveType(caps, GST_VIDEO_CAPS_TYPE_PREFIX)) {
         ASSERT(stream->type == Video);
         signal = SIGNAL_VIDEO_CHANGED;
         stream->videoTrack = RefPtr<WebCore::VideoTrackPrivateGStreamer>(static_cast<WebCore::VideoTrackPrivateGStreamer*>(trackPrivate.get()));
-    } else if (g_str_has_prefix(mediaType, "text")) {
+    } else if (doCapsHaveType(caps, GST_TEXT_CAPS_TYPE_PREFIX)) {
         ASSERT(stream->type == Text);
         signal = SIGNAL_TEXT_CHANGED;
 
index 6661d6a..7f72e47 100644 (file)
@@ -57,8 +57,8 @@ public:
 
     MediaSourcePrivate::AddStatus addSourceBuffer(RefPtr<SourceBufferPrivateGStreamer>);
     void removeSourceBuffer(RefPtr<SourceBufferPrivateGStreamer>);
-    void attachTrack(RefPtr<SourceBufferPrivateGStreamer>, RefPtr<TrackPrivateBase>, GstStructure*, GstCaps*);
-    void reattachTrack(RefPtr<SourceBufferPrivateGStreamer>, RefPtr<TrackPrivateBase>, const char*);
+    void attachTrack(RefPtr<SourceBufferPrivateGStreamer>, RefPtr<TrackPrivateBase>, GstCaps*);
+    void reattachTrack(RefPtr<SourceBufferPrivateGStreamer>, RefPtr<TrackPrivateBase>, GstCaps*);
     void notifyDurationChanged();
 
     // From MediaSourceGStreamer.
index 69efc1c..042e03a 100644 (file)
@@ -452,18 +452,13 @@ gboolean webKitMediaSrcQueryWithParent(GstPad* pad, GstObject* parent, GstQuery*
 
 void webKitMediaSrcUpdatePresentationSize(GstCaps* caps, Stream* stream)
 {
-    GstStructure* structure = gst_caps_get_structure(caps, 0);
-    const gchar* structureName = gst_structure_get_name(structure);
-    GstVideoInfo info;
-
     GST_OBJECT_LOCK(stream->parent);
-    if (g_str_has_prefix(structureName, "video/") && gst_video_info_from_caps(&info, caps)) {
-        float width, height;
-
-        // FIXME: Correct?.
-        width = info.width;
-        height = info.height * ((float) info.par_d / (float) info.par_n);
-        stream->presentationSize = WebCore::FloatSize(width, height);
+    if (WebCore::doCapsHaveType(caps, GST_VIDEO_CAPS_TYPE_PREFIX)) {
+        std::optional<WebCore::FloatSize> size = WebCore::getVideoResolutionFromCaps(caps);
+        if (size.has_value())
+            stream->presentationSize = size.value();
+        else
+            stream->presentationSize = WebCore::FloatSize();
     } else
         stream->presentationSize = WebCore::FloatSize();