Diff
Modified: trunk/Source/WebCore/ChangeLog (231632 => 231633)
--- trunk/Source/WebCore/ChangeLog 2018-05-10 06:52:31 UTC (rev 231632)
+++ trunk/Source/WebCore/ChangeLog 2018-05-10 07:11:19 UTC (rev 231633)
@@ -1,3 +1,53 @@
+2018-05-10 Yacine Bandou <yacine.bandou_...@softathome.com>
+
+ [EME][GStreamer] Move the decryptor from AppendPipeline to PlaybackPipeline.
+ https://bugs.webkit.org/show_bug.cgi?id=181855
+
+ Reviewed by Xabier Rodriguez-Calvar.
+
+ The goal of this move is to handle the limitation of SVP (Secure Video Path) memory size.
+
+ When the decryptor is in the AppendPipeline and we use SVP, we buffer in MediaSource queue
+ the decrypted GstBuffers that are in SVP memory.
+ This behavior cause an out-of-memory error, because we are limited in SVP memory size.
+
+ By moving the decryptor in PlaybackPipeline, we avoid to buffer the decrypted GstBuffers
+ which use the SVP memory and we buffer the encrypted GstBuffers that are in system memory.
+
+ This new architecture also allows to start the buffering before obtaining the DRM license
+ and it makes easier to manage dynamic change of the license or Key.
+
+ The decryptor is auto plugged by GStreamer playbin in PlaybackPipeline.
+
+ SVP: Secure Video Path also named trusted or protected video path, it is a memory which is
+ protected by a hardware access control engine, it is not accessible to other unauthorised
+ software or hardware components.
+
+ Tests:
+ media/encrypted-media/clearKey/clearKey-cenc-audio-playback-mse.html
+ media/encrypted-media/clearKey/clearKey-cenc-video-playback-mse.html
+
+ * platform/graphics/gstreamer/eme/WebKitCommonEncryptionDecryptorGStreamer.cpp:
+ (webkitMediaCommonEncryptionDecryptSinkEventHandler):
+ * platform/graphics/gstreamer/mse/AppendPipeline.cpp:
+ (WebCore::dumpAppendState):
+ (WebCore::AppendPipeline::AppendPipeline):
+ (WebCore::AppendPipeline::handleNeedContextSyncMessage):
+ (WebCore::AppendPipeline::handleAppsrcNeedDataReceived):
+ (WebCore::AppendPipeline::setAppendState):
+ (WebCore::AppendPipeline::parseDemuxerSrcPadCaps):
+ (WebCore::AppendPipeline::appsinkNewSample):
+ (WebCore::AppendPipeline::connectDemuxerSrcPadToAppsinkFromAnyThread):
+ (WebCore::AppendPipeline::disconnectDemuxerSrcPadFromAppsinkFromAnyThread):
+ (WebCore::appendPipelineElementMessageCallback): Deleted.
+ (WebCore::AppendPipeline::handleElementMessage): Deleted.
+ (WebCore::AppendPipeline::dispatchPendingDecryptionStructure): Deleted.
+ (WebCore::AppendPipeline::dispatchDecryptionStructure): Deleted.
+ * platform/graphics/gstreamer/mse/AppendPipeline.h:
+ * platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp:
+ (WebCore::MediaPlayerPrivateGStreamerMSE::attemptToDecryptWithInstance):
+ * platform/graphics/gstreamer/mse/PlaybackPipeline.cpp:
+
2018-05-09 Nan Wang <n_w...@apple.com>
AX: VoiceOver iframe scrolling focus jumping bug
Modified: trunk/Source/WebCore/platform/graphics/gstreamer/eme/WebKitCommonEncryptionDecryptorGStreamer.cpp (231632 => 231633)
--- trunk/Source/WebCore/platform/graphics/gstreamer/eme/WebKitCommonEncryptionDecryptorGStreamer.cpp 2018-05-10 06:52:31 UTC (rev 231632)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/eme/WebKitCommonEncryptionDecryptorGStreamer.cpp 2018-05-10 07:11:19 UTC (rev 231633)
@@ -299,23 +299,6 @@
gboolean result = FALSE;
switch (GST_EVENT_TYPE(event)) {
- case GST_EVENT_PROTECTION: {
- const char* systemId = nullptr;
-
- gst_event_parse_protection(event, &systemId, nullptr, nullptr);
- GST_TRACE_OBJECT(self, "received protection event for %s", systemId);
-
- if (!g_strcmp0(systemId, klass->protectionSystemId)) {
- GST_DEBUG_OBJECT(self, "sending protection event to the pipeline");
- gst_element_post_message(GST_ELEMENT(self),
- gst_message_new_element(GST_OBJECT(self),
- gst_structure_new("drm-key-needed", "event", GST_TYPE_EVENT, event, nullptr)));
- }
-
- gst_event_unref(event);
- result = TRUE;
- break;
- }
case GST_EVENT_CUSTOM_DOWNSTREAM_OOB: {
if (klass->handleKeyResponse(self, event)) {
GST_DEBUG_OBJECT(self, "key received");
Modified: trunk/Source/WebCore/platform/graphics/gstreamer/mse/AppendPipeline.cpp (231632 => 231633)
--- trunk/Source/WebCore/platform/graphics/gstreamer/mse/AppendPipeline.cpp 2018-05-10 06:52:31 UTC (rev 231632)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/mse/AppendPipeline.cpp 2018-05-10 07:11:19 UTC (rev 231633)
@@ -55,8 +55,6 @@
return "NotStarted";
case AppendPipeline::AppendState::Ongoing:
return "Ongoing";
- case AppendPipeline::AppendState::KeyNegotiation:
- return "KeyNegotiation";
case AppendPipeline::AppendState::DataStarve:
return "DataStarve";
case AppendPipeline::AppendState::Sampling:
@@ -93,13 +91,6 @@
appendPipeline->handleApplicationMessage(message);
}
-#if ENABLE(ENCRYPTED_MEDIA)
-static void appendPipelineElementMessageCallback(GstBus*, GstMessage* message, AppendPipeline* appendPipeline)
-{
- appendPipeline->handleElementMessage(message);
-}
-#endif
-
static void appendPipelineStateChangeMessageCallback(GstBus*, GstMessage* message, AppendPipeline* appendPipeline)
{
appendPipeline->handleStateChangeMessage(message);
@@ -131,9 +122,6 @@
g_signal_connect(m_bus.get(), "sync-message::need-context", G_CALLBACK(appendPipelineNeedContextMessageCallback), this);
g_signal_connect(m_bus.get(), "message::application", G_CALLBACK(appendPipelineApplicationMessageCallback), this);
-#if ENABLE(ENCRYPTED_MEDIA)
- g_signal_connect(m_bus.get(), "message::element", G_CALLBACK(appendPipelineElementMessageCallback), this);
-#endif
g_signal_connect(m_bus.get(), "message::state-changed", G_CALLBACK(appendPipelineStateChangeMessageCallback), this);
// We assign the created instances here instead of adoptRef() because gst_bin_add_many()
@@ -275,9 +263,6 @@
const gchar* contextType = nullptr;
gst_message_parse_context_type(message, &contextType);
GST_TRACE("context type: %s", contextType);
- if (!g_strcmp0(contextType, "drm-preferred-decryption-system-id")
- && m_appendState != AppendPipeline::AppendState::KeyNegotiation)
- setAppendState(AppendPipeline::AppendState::KeyNegotiation);
// MediaPlayerPrivateGStreamerBase will take care of setting up encryption.
if (m_playerPrivate)
@@ -329,25 +314,6 @@
ASSERT_NOT_REACHED();
}
-#if ENABLE(ENCRYPTED_MEDIA)
-void AppendPipeline::handleElementMessage(GstMessage* message)
-{
- ASSERT(WTF::isMainThread());
-
- const GstStructure* structure = gst_message_get_structure(message);
- GST_TRACE("%s message from %s", gst_structure_get_name(structure), GST_MESSAGE_SRC_NAME(message));
- if (m_playerPrivate && gst_structure_has_name(structure, "drm-key-needed")) {
- if (m_appendState != AppendPipeline::AppendState::KeyNegotiation)
- setAppendState(AppendPipeline::AppendState::KeyNegotiation);
-
- GST_DEBUG("sending drm-key-needed message from %s to the player", GST_MESSAGE_SRC_NAME(message));
- GRefPtr<GstEvent> event;
- gst_structure_get(structure, "event", GST_TYPE_EVENT, &event.outPtr(), nullptr);
- m_playerPrivate->handleProtectionEvent(event.get());
- }
-}
-#endif
-
void AppendPipeline::handleStateChangeMessage(GstMessage* message)
{
ASSERT(WTF::isMainThread());
@@ -373,7 +339,7 @@
return;
}
- ASSERT(m_appendState == AppendState::KeyNegotiation || m_appendState == AppendState::Ongoing || m_appendState == AppendState::Sampling);
+ ASSERT(m_appendState == AppendState::Ongoing || m_appendState == AppendState::Sampling);
ASSERT(!m_appsrcNeedDataReceived);
GST_TRACE("received need-data from appsrc");
@@ -431,8 +397,7 @@
// NotStarted-->Ongoing-->DataStarve-->NotStarted
// | | `->Aborting-->NotStarted
// | `->Sampling-ยทยทยท->Sampling-->LastSample-->NotStarted
- // | | `->Aborting-->NotStarted
- // | `->KeyNegotiation-->Ongoing-->[...]
+ // | `->Aborting-->NotStarted
// `->Aborting-->NotStarted
AppendState oldAppendState = m_appendState;
AppendState nextAppendState = AppendState::Invalid;
@@ -468,19 +433,8 @@
break;
}
break;
- case AppendState::KeyNegotiation:
- switch (newAppendState) {
- case AppendState::Ongoing:
- case AppendState::Invalid:
- ok = true;
- break;
- default:
- break;
- }
- break;
case AppendState::Ongoing:
switch (newAppendState) {
- case AppendState::KeyNegotiation:
case AppendState::Sampling:
case AppendState::Invalid:
ok = true;
@@ -582,18 +536,7 @@
m_demuxerSrcPadCaps = adoptGRef(demuxerSrcPadCaps);
m_streamType = WebCore::MediaSourceStreamTypeGStreamer::Unknown;
-#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;
- }
- }
-#endif
+
const char* originalMediaType = capsMediaType(m_demuxerSrcPadCaps.get());
if (!MediaPlayerPrivateGStreamerMSE::supportsCodec(originalMediaType)) {
m_presentationSize = WebCore::FloatSize();
@@ -673,10 +616,6 @@
{
LockHolder locker(m_newSampleLock);
- // If we were in KeyNegotiation but samples are coming, assume we're already OnGoing
- if (m_appendState == AppendState::KeyNegotiation)
- setAppendState(AppendState::Ongoing);
-
// Ignore samples if we're not expecting them. Refuse processing if we're in Invalid state.
if (m_appendState != AppendState::Ongoing && m_appendState != AppendState::Sampling) {
GST_WARNING("Unexpected sample, appendState=%s", dumpAppendState(m_appendState));
@@ -1009,28 +948,10 @@
currentSrcPad = parserSrcPad;
}
-#if ENABLE(ENCRYPTED_MEDIA)
- if (m_decryptor) {
- gst_object_ref(m_decryptor.get());
- gst_bin_add(GST_BIN(m_pipeline.get()), m_decryptor.get());
- gst_element_sync_state_with_parent(m_decryptor.get());
-
- GRefPtr<GstPad> decryptorSinkPad = adoptGRef(gst_element_get_static_pad(m_decryptor.get(), "sink"));
- GRefPtr<GstPad> decryptorSrcPad = adoptGRef(gst_element_get_static_pad(m_decryptor.get(), "src"));
-
- gst_pad_link(currentSrcPad.get(), decryptorSinkPad.get());
- currentSrcPad = decryptorSrcPad;
- }
-#endif
-
gst_pad_link(currentSrcPad.get(), appsinkSinkPad.get());
gst_element_sync_state_with_parent(m_appsink.get());
-#if ENABLE(ENCRYPTED_MEDIA)
- if (m_pendingDecryptionStructure)
- dispatchPendingDecryptionStructure();
-#endif
gst_element_set_state(m_pipeline.get(), GST_STATE_PAUSED);
gst_element_sync_state_with_parent(m_appsink.get());
@@ -1109,14 +1030,6 @@
GST_DEBUG("Disconnecting appsink");
-#if ENABLE(ENCRYPTED_MEDIA)
- if (m_decryptor) {
- gst_element_set_state(m_decryptor.get(), GST_STATE_NULL);
- gst_bin_remove(GST_BIN(m_pipeline.get()), m_decryptor.get());
- m_decryptor = nullptr;
- }
-#endif
-
if (m_parser) {
gst_element_set_state(m_parser.get(), GST_STATE_NULL);
gst_bin_remove(GST_BIN(m_pipeline.get()), m_parser.get());
@@ -1126,35 +1039,6 @@
GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(m_pipeline.get()), GST_DEBUG_GRAPH_SHOW_ALL, "pad-removed-after");
}
-#if ENABLE(ENCRYPTED_MEDIA)
-void AppendPipeline::dispatchPendingDecryptionStructure()
-{
- ASSERT(m_decryptor);
- ASSERT(m_pendingDecryptionStructure);
- ASSERT(m_appendState == AppendState::KeyNegotiation);
- GST_TRACE("dispatching key to append pipeline %p", this);
-
- // Release the m_pendingDecryptionStructure object since
- // gst_event_new_custom() takes over ownership of it.
- gst_element_send_event(m_pipeline.get(), gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM_OOB, m_pendingDecryptionStructure.release()));
-
- setAppendState(AppendState::Ongoing);
-}
-
-void AppendPipeline::dispatchDecryptionStructure(GUniquePtr<GstStructure>&& structure)
-{
- if (m_appendState == AppendState::KeyNegotiation) {
- GST_TRACE("append pipeline %p in key negotiation", this);
- m_pendingDecryptionStructure = WTFMove(structure);
- if (m_decryptor)
- dispatchPendingDecryptionStructure();
- else
- GST_TRACE("no decryptor yet, waiting for it");
- } else
- GST_TRACE("append pipeline %p not in key negotiation", this);
-}
-#endif
-
static void appendPipelineAppsinkCapsChanged(GObject* appsinkPad, GParamSpec*, AppendPipeline* appendPipeline)
{
GstStructure* structure = gst_structure_new_empty("appsink-caps-changed");
Modified: trunk/Source/WebCore/platform/graphics/gstreamer/mse/AppendPipeline.h (231632 => 231633)
--- trunk/Source/WebCore/platform/graphics/gstreamer/mse/AppendPipeline.h 2018-05-10 06:52:31 UTC (rev 231632)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/mse/AppendPipeline.h 2018-05-10 07:11:19 UTC (rev 231633)
@@ -42,7 +42,7 @@
class AppendPipeline : public ThreadSafeRefCounted<AppendPipeline> {
public:
- enum class AppendState { Invalid, NotStarted, Ongoing, KeyNegotiation, DataStarve, Sampling, LastSample, Aborting };
+ enum class AppendState { Invalid, NotStarted, Ongoing, DataStarve, Sampling, LastSample, Aborting };
AppendPipeline(Ref<MediaSourceClientGStreamerMSE>, Ref<SourceBufferPrivateGStreamer>, MediaPlayerPrivateGStreamerMSE&);
virtual ~AppendPipeline();
@@ -50,9 +50,6 @@
void handleNeedContextSyncMessage(GstMessage*);
void handleApplicationMessage(GstMessage*);
void handleStateChangeMessage(GstMessage*);
-#if ENABLE(ENCRYPTED_MEDIA)
- void handleElementMessage(GstMessage*);
-#endif
gint id();
AppendState appendState() { return m_appendState; }
@@ -60,9 +57,6 @@
GstFlowReturn handleNewAppsinkSample(GstElement*);
GstFlowReturn pushNewBuffer(GstBuffer*);
-#if ENABLE(ENCRYPTED_MEDIA)
- void dispatchDecryptionStructure(GUniquePtr<GstStructure>&&);
-#endif
// Takes ownership of caps.
void parseDemuxerSrcPadCaps(GstCaps*);
@@ -98,9 +92,6 @@
void handleAppsrcNeedDataReceived();
void removeAppsrcDataLeavingProbe();
void setAppsrcDataLeavingProbe();
-#if ENABLE(ENCRYPTED_MEDIA)
- void dispatchPendingDecryptionStructure();
-#endif
Ref<MediaSourceClientGStreamerMSE> m_mediaSourceClient;
Ref<SourceBufferPrivateGStreamer> m_sourceBufferPrivate;
@@ -118,9 +109,6 @@
GRefPtr<GstElement> m_appsrc;
GRefPtr<GstElement> m_demux;
GRefPtr<GstElement> m_parser; // Optional.
-#if ENABLE(ENCRYPTED_MEDIA)
- GRefPtr<GstElement> m_decryptor;
-#endif
// The demuxer has one src stream only, so only one appsink is needed and linked to it.
GRefPtr<GstElement> m_appsink;
@@ -155,9 +143,6 @@
RefPtr<WebCore::TrackPrivateBase> m_track;
GRefPtr<GstBuffer> m_pendingBuffer;
-#if ENABLE(ENCRYPTED_MEDIA)
- GUniquePtr<GstStructure> m_pendingDecryptionStructure;
-#endif
};
} // namespace WebCore.
Modified: trunk/Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp (231632 => 231633)
--- trunk/Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp 2018-05-10 06:52:31 UTC (rev 231632)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp 2018-05-10 07:11:19 UTC (rev 231633)
@@ -955,8 +955,7 @@
gst_structure_set_value(structure.get(), "key-ids", &keyIDList);
gst_structure_set_value(structure.get(), "key-values", &keyValueList);
- for (auto it : m_appendPipelinesMap)
- it.value->dispatchDecryptionStructure(GUniquePtr<GstStructure>(gst_structure_copy(structure.get())));
+ gst_element_send_event(m_playbackPipeline->pipeline(), gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM_OOB, structure.release()));
}
}
#endif
Modified: trunk/Source/WebCore/platform/graphics/gstreamer/mse/PlaybackPipeline.cpp (231632 => 231633)
--- trunk/Source/WebCore/platform/graphics/gstreamer/mse/PlaybackPipeline.cpp 2018-05-10 06:52:31 UTC (rev 231632)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/mse/PlaybackPipeline.cpp 2018-05-10 07:11:19 UTC (rev 231633)
@@ -180,7 +180,10 @@
GUniquePtr<gchar> parserBinName(g_strdup_printf("streamparser%u", padId));
- if (!g_strcmp0(mediaType, "video/x-h264")) {
+ if (areEncryptedCaps(caps)) {
+ GST_DEBUG("It's encrypted content, parsers are not needed before decrypting the content");
+ stream->parser = nullptr;
+ } else if (!g_strcmp0(mediaType, "video/x-h264")) {
GRefPtr<GstCaps> filterCaps = adoptGRef(gst_caps_new_simple("video/x-h264", "alignment", G_TYPE_STRING, "au", nullptr));
GstElement* capsfilter = gst_element_factory_make("capsfilter", nullptr);
g_object_set(capsfilter, "caps", filterCaps.get(), nullptr);