media: Allow config change between clear and encrypted streams
In the demuxer, we allow DecryptConfig change upon config change,
including but not limited to:
- switching between clear and encrypted
- encryption scheme change
Media Renderer implementation should support such changes. The detailed
requirement from the spec's perspective is tracked at:
https://github.com/w3c/encrypted-media/issues/251
Currently the default media Renderer (RendererImpl) supports switching
from encrypted to clear, because:
- Decrypt-and-decode mode: Decrypting{Audio|Video}Decoder supports clear
buffer.
- Decrypt-only mode: DecryptingDemuxerStream supports clear buffer.
However, switching from clear to encrypted is not supported in
RendererImpl, because the clear decoder doesn't support decryption. This
will be fixed in a later CL.
BUG=597443
TEST=Updated pipeline_integration_tests.
Review-Url: https://codereview.chromium.org/2543623003
Cr-Commit-Position: refs/heads/master@{#451212}
diff --git a/chrome/browser/media/encrypted_media_browsertest.cc b/chrome/browser/media/encrypted_media_browsertest.cc
index d4d06ee7..a905b440 100644
--- a/chrome/browser/media/encrypted_media_browsertest.cc
+++ b/chrome/browser/media/encrypted_media_browsertest.cc
@@ -7,6 +7,7 @@
#include "base/command_line.h"
#include "base/path_service.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "chrome/browser/media/media_browsertest.h"
@@ -43,6 +44,8 @@
#include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR.
+namespace chrome {
+
// Available key systems.
const char kClearKeyKeySystem[] = "org.w3.clearkey";
const char kExternalClearKeyKeySystem[] = "org.chromium.externalclearkey";
@@ -101,9 +104,14 @@
const char kDefaultEmePlayer[] = "eme_player.html";
// The type of video src used to load media.
-enum SrcType {
- SRC,
- MSE
+enum class SrcType { SRC, MSE };
+
+// Must be in sync with CONFIG_CHANGE_TYPE in eme_player_js/global.js
+enum class ConfigChangeType {
+ CLEAR_TO_CLEAR = 0,
+ CLEAR_TO_ENCRYPTED = 1,
+ ENCRYPTED_TO_CLEAR = 2,
+ ENCRYPTED_TO_ENCRYPTED = 3,
};
// Whether the video should be played once or twice.
@@ -164,7 +172,7 @@
query_params.push_back(std::make_pair("mediaFile", media_file));
query_params.push_back(std::make_pair("mediaType", media_type));
query_params.push_back(std::make_pair("keySystem", key_system));
- if (src_type == MSE)
+ if (src_type == SrcType::MSE)
query_params.push_back(std::make_pair("useMSE", "1"));
if (force_invalid_response)
query_params.push_back(std::make_pair("forceInvalidResponse", "1"));
@@ -301,7 +309,7 @@
// Since we do not test playback, arbitrarily choose a test file and source
// type.
RunEncryptedMediaTest(kDefaultEmePlayer, "bear-a_enc-a.webm",
- kWebMVorbisAudioOnly, key_system, SRC,
+ kWebMVorbisAudioOnly, key_system, SrcType::SRC,
kNoSessionToLoad, false, PlayCount::ONCE,
expected_title);
}
@@ -310,8 +318,9 @@
const std::string& session_to_load,
const std::string& expected_title) {
RunEncryptedMediaTest(kDefaultEmePlayer, "bear-320x240-v_enc-v.webm",
- kWebMVP8VideoOnly, key_system, SRC, session_to_load,
- false, PlayCount::ONCE, expected_title);
+ kWebMVP8VideoOnly, key_system, SrcType::SRC,
+ session_to_load, false, PlayCount::ONCE,
+ expected_title);
}
protected:
@@ -381,14 +390,26 @@
kNoSessionToLoad, false, PlayCount::ONCE, kEnded);
}
- void TestConfigChange() {
+ void TestConfigChange(ConfigChangeType config_change_type) {
+ // TODO(xhwang): Even when config change or playback is not supported we
+ // still start Chrome only to return directly here. We probably should not
+ // run these test cases at all. See http://crbug.com/693288
+ if (CurrentSourceType() != SrcType::MSE) {
+ DVLOG(0) << "Config change only happens when using MSE.";
+ return;
+ }
+ if (!IsPlayBackPossible(CurrentKeySystem())) {
+ DVLOG(0) << "Skipping test - ConfigChange test requires video playback.";
+ return;
+ }
+
base::StringPairs query_params;
query_params.push_back(std::make_pair("keySystem", CurrentKeySystem()));
- query_params.push_back(std::make_pair("runEncrypted", "1"));
- RunEncryptedMediaTestPage("mse_config_change.html",
- CurrentKeySystem(),
- query_params,
- kEnded);
+ query_params.push_back(std::make_pair(
+ "configChangeType",
+ base::IntToString(static_cast<int>(config_change_type))));
+ RunEncryptedMediaTestPage("mse_config_change.html", CurrentKeySystem(),
+ query_params, kEnded);
}
std::string ConvertContainerFormat(EncryptedContainer format) {
@@ -437,24 +458,26 @@
#if !defined(OS_ANDROID)
INSTANTIATE_TEST_CASE_P(SRC_ClearKey,
EncryptedMediaTest,
- Combine(Values(kClearKeyKeySystem), Values(SRC)));
+ Combine(Values(kClearKeyKeySystem),
+ Values(SrcType::SRC)));
#endif // !defined(OS_ANDROID)
INSTANTIATE_TEST_CASE_P(MSE_ClearKey,
EncryptedMediaTest,
- Combine(Values(kClearKeyKeySystem), Values(MSE)));
+ Combine(Values(kClearKeyKeySystem),
+ Values(SrcType::MSE)));
// External Clear Key is currently only used on platforms that use Pepper CDMs.
#if BUILDFLAG(ENABLE_PEPPER_CDMS)
INSTANTIATE_TEST_CASE_P(SRC_ExternalClearKey,
EncryptedMediaTest,
Combine(Values(kExternalClearKeyKeySystem),
- Values(SRC)));
+ Values(SrcType::SRC)));
INSTANTIATE_TEST_CASE_P(MSE_ExternalClearKey,
EncryptedMediaTest,
Combine(Values(kExternalClearKeyKeySystem),
- Values(MSE)));
+ Values(SrcType::MSE)));
const char kExternalClearKeyDecryptOnlyKeySystem[] =
"org.chromium.externalclearkey.decryptonly";
@@ -463,14 +486,15 @@
INSTANTIATE_TEST_CASE_P(MSE_ExternalClearKeyDecryptOnly,
EncryptedMediaTest,
Combine(Values(kExternalClearKeyDecryptOnlyKeySystem),
- Values(MSE)));
+ Values(SrcType::MSE)));
#endif // BUILDFLAG(ENABLE_PEPPER_CDMS)
#if defined(WIDEVINE_CDM_AVAILABLE)
#if !defined(OS_CHROMEOS)
INSTANTIATE_TEST_CASE_P(MSE_Widevine,
EncryptedMediaTest,
- Combine(Values(kWidevineKeySystem), Values(MSE)));
+ Combine(Values(kWidevineKeySystem),
+ Values(SrcType::MSE)));
#endif // !defined(OS_CHROMEOS)
#endif // defined(WIDEVINE_CDM_AVAILABLE)
@@ -529,12 +553,28 @@
RunInvalidResponseTest();
}
-IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, ConfigChangeVideo) {
- if (!IsPlayBackPossible(CurrentKeySystem())) {
- DVLOG(0) << "Skipping test - ConfigChange test requires video playback.";
- return;
- }
- TestConfigChange();
+// Strictly speaking this is not an "encrypted" media test. Keep it here for
+// completeness.
+IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, ConfigChangeVideo_ClearToClear) {
+ TestConfigChange(ConfigChangeType::CLEAR_TO_CLEAR);
+}
+
+// TODO(xhwang): Support switching from clear to encrypted and fix the test
+// expectation. Currently this test passes when we do decrypt-and-decode but
+// fails when we do decrypt-only due to how decoder reselection during config
+// change is handled. See http://crbug.com/597443
+IN_PROC_BROWSER_TEST_P(EncryptedMediaTest,
+ DISABLED_ConfigChangeVideo_ClearToEncrypted) {
+ TestConfigChange(ConfigChangeType::CLEAR_TO_ENCRYPTED);
+}
+
+IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, ConfigChangeVideo_EncryptedToClear) {
+ TestConfigChange(ConfigChangeType::ENCRYPTED_TO_CLEAR);
+}
+
+IN_PROC_BROWSER_TEST_P(EncryptedMediaTest,
+ ConfigChangeVideo_EncryptedToEncrypted) {
+ TestConfigChange(ConfigChangeType::ENCRYPTED_TO_ENCRYPTED);
}
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, FrameSizeChangeVideo) {
@@ -567,7 +607,7 @@
#endif
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, MAYBE_Playback_VideoOnly_MP4) {
// MP4 without MSE is not support yet, http://crbug.com/170793.
- if (CurrentSourceType() != MSE) {
+ if (CurrentSourceType() != SrcType::MSE) {
DVLOG(0) << "Skipping test; Can only play MP4 encrypted streams by MSE.";
return;
}
@@ -576,7 +616,7 @@
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioOnly_MP4) {
// MP4 without MSE is not support yet, http://crbug.com/170793.
- if (CurrentSourceType() != MSE) {
+ if (CurrentSourceType() != SrcType::MSE) {
DVLOG(0) << "Skipping test; Can only play MP4 encrypted streams by MSE.";
return;
}
@@ -585,7 +625,7 @@
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoOnly_MP4_VP9) {
// MP4 without MSE is not support yet, http://crbug.com/170793.
- if (CurrentSourceType() != MSE) {
+ if (CurrentSourceType() != SrcType::MSE) {
DVLOG(0) << "Skipping test; Can only play MP4 encrypted streams by MSE.";
return;
}
@@ -595,7 +635,7 @@
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest,
Playback_EncryptedVideo_MP4_ClearAudio_WEBM) {
// MP4 without MSE is not support yet, http://crbug.com/170793.
- if (CurrentSourceType() != MSE) {
+ if (CurrentSourceType() != SrcType::MSE) {
DVLOG(0) << "Skipping test; Can only play MP4 encrypted streams by MSE.";
return;
}
@@ -610,7 +650,7 @@
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest,
Playback_ClearVideo_WEBM_EncryptedAudio_MP4) {
// MP4 without MSE is not support yet, http://crbug.com/170793.
- if (CurrentSourceType() != MSE) {
+ if (CurrentSourceType() != SrcType::MSE) {
DVLOG(0) << "Skipping test; Can only play MP4 encrypted streams by MSE.";
return;
}
@@ -625,7 +665,7 @@
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest,
Playback_EncryptedVideo_WEBM_EncryptedAudio_MP4) {
// MP4 without MSE is not support yet, http://crbug.com/170793.
- if (CurrentSourceType() != MSE) {
+ if (CurrentSourceType() != SrcType::MSE) {
DVLOG(0) << "Skipping test; Can only play MP4 encrypted streams by MSE.";
return;
}
@@ -642,7 +682,7 @@
// The parent key system cannot be used when creating MediaKeys.
IN_PROC_BROWSER_TEST_F(WVEncryptedMediaTest, ParentThrowsException) {
RunEncryptedMediaTest(kDefaultEmePlayer, "bear-a_enc-a.webm",
- kWebMVorbisAudioOnly, "com.widevine", MSE,
+ kWebMVorbisAudioOnly, "com.widevine", SrcType::MSE,
kNoSessionToLoad, false, PlayCount::ONCE,
kEmeNotSupportedError);
}
@@ -705,3 +745,5 @@
}
#endif // BUILDFLAG(ENABLE_PEPPER_CDMS)
+
+} // namespace chrome