Title: [272055] trunk
Revision
272055
Author
[email protected]
Date
2021-01-29 02:36:36 -0800 (Fri, 29 Jan 2021)

Log Message

[GStreamer][Playbin3] Support for CEA-608 closed captioned media
https://bugs.webkit.org/show_bug.cgi?id=220654

Reviewed by Xabier Rodriguez-Calvar.

Source/WebCore:

Playbin2 currently doesn't support closed-caption formats such as CEA-608 and CEA-708.
However playbin3's decodebin3 will expose a source pad for these, so our text combiner can
handle this format, by adding a custom encoder that converts CEA-608 to WebVTT.

No new tests, although media/media-captions.html and media/track/track-in-band-style.html
will now pass when this env var is set WEBKIT_GST_USE_PLAYBIN3=1.

* Modules/mediacontrols/mediaControlsAdwaita.css: Synchronize text-track-container and cue
CSS with mediaControlsBase.css.
(video::-webkit-media-text-track-container,):
(video::-webkit-media-text-track-container):
(video::cue):
(video::cue(:future)):
* platform/graphics/gstreamer/InbandTextTrackPrivateGStreamer.cpp: Set track kind according
to the GstStream format this track represents.
(WebCore::InbandTextTrackPrivateGStreamer::InbandTextTrackPrivateGStreamer):
* platform/graphics/gstreamer/InbandTextTrackPrivateGStreamer.h:
* platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp: Drive-by, check
WEBKIT_GST_USE_PLAYBIN3 contents and sprinkle a few more debug calls.
(WebCore::MediaPlayerPrivateGStreamer::doSeek):
(WebCore::MediaPlayerPrivateGStreamer::timeChanged):
(WebCore::MediaPlayerPrivateGStreamer::createGSTPlayBin):
* platform/graphics/gstreamer/TextCombinerGStreamer.cpp: Plug custom encoder handling
conversion of CEA-608 to WebVTT.
(webKitTextCombinerHandleCapsEvent):
(webkitTextCombinerReleasePad):
(webKitTextCombinerConstructed):

LayoutTests:

* media/track/track-in-band-style-expected.txt:
* media/track/track-in-band-style.html:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (272054 => 272055)


--- trunk/LayoutTests/ChangeLog	2021-01-29 10:01:27 UTC (rev 272054)
+++ trunk/LayoutTests/ChangeLog	2021-01-29 10:36:36 UTC (rev 272055)
@@ -1,3 +1,13 @@
+2021-01-29  Philippe Normand  <[email protected]>
+
+        [GStreamer][Playbin3] Support for CEA-608 closed captioned media
+        https://bugs.webkit.org/show_bug.cgi?id=220654
+
+        Reviewed by Xabier Rodriguez-Calvar.
+
+        * media/track/track-in-band-style-expected.txt:
+        * media/track/track-in-band-style.html:
+
 2021-01-28  Sergio Villar Senin  <[email protected]>
 
         [css-flexbox] REGRESSION(r266695): content inside a `<button>` inside a flex container has a height of `0` without a declared `min-height`

Modified: trunk/LayoutTests/media/track/track-in-band-style-expected.txt (272054 => 272055)


--- trunk/LayoutTests/media/track/track-in-band-style-expected.txt	2021-01-29 10:01:27 UTC (rev 272054)
+++ trunk/LayoutTests/media/track/track-in-band-style-expected.txt	2021-01-29 10:36:36 UTC (rev 272055)
@@ -13,7 +13,7 @@
 EVENT(cuechange)
 
 ** Test current cue colors
-EXPECTED (cueNode.style.color == 'rgb(255, 255, 255)') OK
-EXPECTED (cueNode.style.backgroundColor == 'rgb(0, 0, 0)') OK
+EXPECTED (getComputedStyle(cueNode).color == 'rgb(255, 255, 255)') OK
+EXPECTED (getComputedStyle(cueNode).backgroundColor == 'rgba(0, 0, 0, 0.8)') OK
 END OF TEST
 

Modified: trunk/LayoutTests/media/track/track-in-band-style.html (272054 => 272055)


--- trunk/LayoutTests/media/track/track-in-band-style.html	2021-01-29 10:01:27 UTC (rev 272054)
+++ trunk/LayoutTests/media/track/track-in-band-style.html	2021-01-29 10:36:36 UTC (rev 272055)
@@ -25,9 +25,9 @@
                     }
     
                     consoleWrite("<br><i>** Test current cue colors<" + "/i>");
-                    testExpected("cueNode.style.color", "rgb(255, 255, 255)");
-                    testExpected("cueNode.style.backgroundColor", "rgb(0, 0, 0)");
-    
+                    testExpected("getComputedStyle(cueNode).color", "rgb(255, 255, 255)");
+                    testExpected("getComputedStyle(cueNode).backgroundColor", "rgba(0, 0, 0, 0.8)");
+
                     endTest();
                 }
                 

Modified: trunk/Source/WebCore/ChangeLog (272054 => 272055)


--- trunk/Source/WebCore/ChangeLog	2021-01-29 10:01:27 UTC (rev 272054)
+++ trunk/Source/WebCore/ChangeLog	2021-01-29 10:36:36 UTC (rev 272055)
@@ -1,3 +1,38 @@
+2021-01-29  Philippe Normand  <[email protected]>
+
+        [GStreamer][Playbin3] Support for CEA-608 closed captioned media
+        https://bugs.webkit.org/show_bug.cgi?id=220654
+
+        Reviewed by Xabier Rodriguez-Calvar.
+
+        Playbin2 currently doesn't support closed-caption formats such as CEA-608 and CEA-708.
+        However playbin3's decodebin3 will expose a source pad for these, so our text combiner can
+        handle this format, by adding a custom encoder that converts CEA-608 to WebVTT.
+
+        No new tests, although media/media-captions.html and media/track/track-in-band-style.html
+        will now pass when this env var is set WEBKIT_GST_USE_PLAYBIN3=1.
+
+        * Modules/mediacontrols/mediaControlsAdwaita.css: Synchronize text-track-container and cue
+        CSS with mediaControlsBase.css.
+        (video::-webkit-media-text-track-container,):
+        (video::-webkit-media-text-track-container):
+        (video::cue):
+        (video::cue(:future)):
+        * platform/graphics/gstreamer/InbandTextTrackPrivateGStreamer.cpp: Set track kind according
+        to the GstStream format this track represents.
+        (WebCore::InbandTextTrackPrivateGStreamer::InbandTextTrackPrivateGStreamer):
+        * platform/graphics/gstreamer/InbandTextTrackPrivateGStreamer.h:
+        * platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp: Drive-by, check
+        WEBKIT_GST_USE_PLAYBIN3 contents and sprinkle a few more debug calls.
+        (WebCore::MediaPlayerPrivateGStreamer::doSeek):
+        (WebCore::MediaPlayerPrivateGStreamer::timeChanged):
+        (WebCore::MediaPlayerPrivateGStreamer::createGSTPlayBin):
+        * platform/graphics/gstreamer/TextCombinerGStreamer.cpp: Plug custom encoder handling
+        conversion of CEA-608 to WebVTT.
+        (webKitTextCombinerHandleCapsEvent):
+        (webkitTextCombinerReleasePad):
+        (webKitTextCombinerConstructed):
+
 2021-01-28  Sergio Villar Senin  <[email protected]>
 
         [css-flexbox] REGRESSION(r266695): content inside a `<button>` inside a flex container has a height of `0` without a declared `min-height`

Modified: trunk/Source/WebCore/Modules/mediacontrols/mediaControlsAdwaita.css (272054 => 272055)


--- trunk/Source/WebCore/Modules/mediacontrols/mediaControlsAdwaita.css	2021-01-29 10:01:27 UTC (rev 272054)
+++ trunk/Source/WebCore/Modules/mediacontrols/mediaControlsAdwaita.css	2021-01-29 10:36:36 UTC (rev 272055)
@@ -469,3 +469,38 @@
 video::-webkit-media-controls-panel button[disabled] {
     filter: brightness(50%);
 }
+
+video::-webkit-media-text-track-container,
+audio::-webkit-media-text-track-container {
+    position: relative;
+    -webkit-flex: 1 1 auto;
+}
+
+video::-webkit-media-text-track-container {
+    overflow: hidden;
+    padding-bottom: 5px;
+    z-index: 0;
+
+    text-align: center;
+    color: rgba(255, 255, 255, 1);
+
+    letter-spacing: normal;
+    word-spacing: normal;
+    text-transform: none;
+    text-indent: 0;
+    text-decoration: none;
+    pointer-events: none;
+    -webkit-user-select: none;
+
+    flex: 1 1 auto;
+
+    -webkit-line-box-contain: block inline-box replaced;
+}
+
+video::cue {
+    background-color: rgba(0, 0, 0, 0.8);
+}
+
+video::cue(:future) {
+    color: gray;
+}

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/InbandTextTrackPrivateGStreamer.cpp (272054 => 272055)


--- trunk/Source/WebCore/platform/graphics/gstreamer/InbandTextTrackPrivateGStreamer.cpp	2021-01-29 10:01:27 UTC (rev 272054)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/InbandTextTrackPrivateGStreamer.cpp	2021-01-29 10:36:36 UTC (rev 272055)
@@ -42,6 +42,7 @@
 InbandTextTrackPrivateGStreamer::InbandTextTrackPrivateGStreamer(gint index, GRefPtr<GstPad> pad)
     : InbandTextTrackPrivate(CueFormat::WebVTT)
     , TrackPrivateBaseGStreamer(this, index, pad)
+    , m_kind(Kind::Subtitles)
 {
     m_eventProbe = gst_pad_add_probe(m_pad.get(), GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, [] (GstPad*, GstPadProbeInfo* info, gpointer userData) -> GstPadProbeReturn {
         auto* track = static_cast<InbandTextTrackPrivateGStreamer*>(userData);
@@ -64,6 +65,11 @@
 {
     m_streamId = gst_stream_get_stream_id(stream.get());
     GST_INFO("Track %d got stream start for stream %s.", m_index, m_streamId.utf8().data());
+
+    GST_DEBUG("Stream %" GST_PTR_FORMAT, stream.get());
+    auto caps = adoptGRef(gst_stream_get_caps(stream.get()));
+    const char* mediaType = capsMediaType(caps.get());
+    m_kind = g_str_has_prefix(mediaType, "closedcaption/") ? Kind::Captions : Kind::Subtitles;
 }
 
 void InbandTextTrackPrivateGStreamer::disconnect()

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/InbandTextTrackPrivateGStreamer.h (272054 => 272055)


--- trunk/Source/WebCore/platform/graphics/gstreamer/InbandTextTrackPrivateGStreamer.h	2021-01-29 10:01:27 UTC (rev 272054)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/InbandTextTrackPrivateGStreamer.h	2021-01-29 10:36:36 UTC (rev 272055)
@@ -51,6 +51,8 @@
 
     void disconnect() override;
 
+    Kind kind() const override { return m_kind; }
+
     AtomString label() const override { return m_label; }
     AtomString language() const override { return m_language; }
 
@@ -71,6 +73,7 @@
     gulong m_eventProbe;
     Vector<GRefPtr<GstSample>> m_pendingSamples;
     String m_streamId;
+    Kind m_kind;
     Lock m_sampleMutex;
 };
 

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp (272054 => 272055)


--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp	2021-01-29 10:01:27 UTC (rev 272054)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp	2021-01-29 10:36:36 UTC (rev 272055)
@@ -488,6 +488,7 @@
     if (!rate)
         rate = 1.0;
 
+    GST_DEBUG_OBJECT(pipeline(), "[Seek] Performing actual seek to %" GST_TIME_FORMAT " (endTime: %" GST_TIME_FORMAT ") at rate %f", GST_TIME_ARGS(toGstClockTime(startTime)), GST_TIME_ARGS(toGstClockTime(endTime)), rate);
     return gst_element_seek(m_pipeline.get(), rate, GST_FORMAT_TIME, seekType,
         GST_SEEK_TYPE_SET, toGstClockTime(startTime), GST_SEEK_TYPE_SET, toGstClockTime(endTime));
 }
@@ -1313,6 +1314,7 @@
 void MediaPlayerPrivateGStreamer::timeChanged()
 {
     updateStates();
+    GST_DEBUG_OBJECT(pipeline(), "Emitting timeChanged notification");
     m_player->timeChanged();
 }
 
@@ -2699,7 +2701,8 @@
     // MSE doesn't support playbin3. Mediastream requires playbin3. Regular
     // playback can use playbin3 on-demand with the WEBKIT_GST_USE_PLAYBIN3
     // environment variable.
-    if ((!isMediaSource() && g_getenv("WEBKIT_GST_USE_PLAYBIN3")) || url.protocolIs("mediastream"))
+    const char* usePlaybin3 = g_getenv("WEBKIT_GST_USE_PLAYBIN3");
+    if ((!isMediaSource() && usePlaybin3 && equal(usePlaybin3, "1")) || url.protocolIs("mediastream"))
         playbinName = "playbin3";
 
     if (m_pipeline) {

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/TextCombinerGStreamer.cpp (272054 => 272055)


--- trunk/Source/WebCore/platform/graphics/gstreamer/TextCombinerGStreamer.cpp	2021-01-29 10:01:27 UTC (rev 272054)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/TextCombinerGStreamer.cpp	2021-01-29 10:36:36 UTC (rev 272055)
@@ -64,6 +64,7 @@
     GRefPtr<GstPad> internalPad;
     g_object_get(combinerPad, "inner-combiner-pad", &internalPad.outPtr(), nullptr);
 
+    auto cea608Caps = adoptGRef(gst_caps_new_empty_simple("closedcaption/x-cea-608"));
     auto textCaps = adoptGRef(gst_caps_new_empty_simple("text/x-raw"));
     if (gst_caps_can_intersect(textCaps.get(), caps)) {
         // Caps are plain text, we want a WebVTT encoder between the ghostpad and the combinerElement.
@@ -87,12 +88,48 @@
 
             gst_pad_link(srcPad.get(), internalPad.get());
         } // Else: pipeline is already correct.
+    } else if (gst_caps_can_intersect(cea608Caps.get(), caps)) {
+        if (!isGStreamerPluginAvailable("rsclosedcaption") || !isGStreamerPluginAvailable("closedcaption")) {
+            WTFLogAlways("GStreamer closedcaption plugins are missing. Please install gst-plugins-bad and gst-plugins-rs");
+            return;
+        }
+
+        GST_DEBUG_OBJECT(combiner, "Converting CEA-608 closed captions to WebVTT.");
+        auto* encoder = gst_bin_new(nullptr);
+        auto* queue = gst_element_factory_make("queue", nullptr);
+        auto* converter = gst_element_factory_make("ccconverter", nullptr);
+        auto* rawCapsFilter = gst_element_factory_make("capsfilter", nullptr);
+        auto* webvttEncoder = gst_element_factory_make("cea608tott", nullptr);
+        auto* vttCapsFilter = gst_element_factory_make("capsfilter", nullptr);
+
+        auto rawCaps = adoptGRef(gst_caps_new_simple("closedcaption/x-cea-608", "format", G_TYPE_STRING, "raw", nullptr));
+        g_object_set(rawCapsFilter, "caps", rawCaps.get(), nullptr);
+        auto vttCaps = adoptGRef(gst_caps_new_empty_simple("application/x-subtitle-vtt"));
+        g_object_set(vttCapsFilter, "caps", vttCaps.get(), nullptr);
+
+        gst_bin_add_many(GST_BIN_CAST(encoder), queue, converter, rawCapsFilter, webvttEncoder, vttCapsFilter, nullptr);
+        gst_element_link_many(queue, converter, rawCapsFilter, webvttEncoder, vttCapsFilter, nullptr);
+
+        auto encoderSinkPad = adoptGRef(gst_element_get_static_pad(queue, "sink"));
+        auto* ghostSinkPad = gst_ghost_pad_new("sink", encoderSinkPad.get());
+        gst_element_add_pad(encoder, ghostSinkPad);
+
+        auto encoderSrcPad = adoptGRef(gst_element_get_static_pad(vttCapsFilter, "src"));
+        auto* ghostSrcPad = gst_ghost_pad_new("src", encoderSrcPad.get());
+        gst_element_add_pad(encoder, ghostSrcPad);
+
+        gst_bin_add(GST_BIN_CAST(combiner), encoder);
+        gst_element_sync_state_with_parent(encoder);
+
+        gst_ghost_pad_set_target(GST_GHOST_PAD(pad), ghostSinkPad);
+        gst_pad_link(ghostSrcPad, internalPad.get());
     } else {
-        // Caps are not plain text, we assume it's WebVTT.
+        // Caps are not plain text or CEA-608, we assume it's WebVTT.
 
         // Remove the WebVTT encoder if present.
-        if (target && gstElementFactoryEquals(targetParent.get(), "webvttenc"_s)) {
+        if (target && targetParent) {
             GST_DEBUG_OBJECT(combiner, "Removing WebVTT encoder");
+            gst_element_set_state(targetParent.get(), GST_STATE_NULL);
             gst_bin_remove(GST_BIN_CAST(combiner), targetParent.get());
             target = nullptr;
             targetParent = nullptr;
@@ -131,7 +168,7 @@
     if (auto target = adoptGRef(gst_ghost_pad_get_target(GST_GHOST_PAD(pad)))) {
         auto parent = adoptGRef(gst_pad_get_parent_element(target.get()));
         ASSERT(parent);
-        if (gstElementFactoryEquals(parent.get(), "webvttenc"_s)) {
+        if (parent) {
             gst_element_set_state(parent.get(), GST_STATE_NULL);
             gst_bin_remove(GST_BIN_CAST(combiner), parent.get());
         }
@@ -150,9 +187,9 @@
     auto* combiner = WEBKIT_TEXT_COMBINER(object);
     auto* priv = combiner->priv;
 
-    // For now a funnel is used, but a better combiner, compatible with playbin3 use-cases, would be concat.
-    priv->combinerElement = gst_element_factory_make("funnel", nullptr);
+    priv->combinerElement = gst_element_factory_make("concat", nullptr);
     ASSERT(priv->combinerElement);
+    g_object_set(priv->combinerElement.get(), "adjust-base", FALSE, nullptr);
 
     gst_bin_add(GST_BIN_CAST(combiner), priv->combinerElement.get());
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to