Cleanup merge conflicts after merging Cobalt 24 support Change-Id: I802473fd11c1f83f490c1845063b360bfcc763f8
diff --git a/LICENSE b/LICENSE index d645695..6b2e4a9 100644 --- a/LICENSE +++ b/LICENSE
@@ -200,3 +200,82 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + +---------------------------------------------------------------------- + +UNICODE LICENSE V3 + +COPYRIGHT AND PERMISSION NOTICE + +Copyright © 2016-2023 Unicode, Inc. + +NOTICE TO USER: Carefully read the following legal agreement. BY +DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING DATA FILES, AND/OR +SOFTWARE, YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE +TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT +DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of data files and any associated documentation (the "Data Files") or +software and any associated documentation (the "Software") to deal in the +Data Files or Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, and/or sell +copies of the Data Files or Software, and to permit persons to whom the +Data Files or Software are furnished to do so, provided that either (a) +this copyright and permission notice appear with all copies of the Data +Files or Software, or (b) this copyright and permission notice appear in +associated Documentation. + +THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF +THIRD PARTY RIGHTS. + +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE +BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, +OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA +FILES OR SOFTWARE. + +Except as contained in this notice, the name of a copyright holder shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in these Data Files or Software without prior written +authorization of the copyright holder. + +---------------------------------------------------------------------- + +ICU License - ICU 1.8.1 to ICU 57.1 + +COPYRIGHT AND PERMISSION NOTICE + +Copyright (c) 1995-2016 International Business Machines Corporation and others +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, and/or sell copies of the Software, and to permit persons +to whom the Software is furnished to do so, provided that the above +copyright notice(s) and this permission notice appear in all copies of +the Software and that both the above copyright notice(s) and this +permission notice appear in supporting documentation. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY +SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER +RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +Except as contained in this notice, the name of a copyright holder +shall not be used in advertising or otherwise to promote the sale, use +or other dealings in this Software without prior written authorization +of the copyright holder. + +All trademarks and registered trademarks mentioned herein are the +property of their respective owners.
diff --git a/NOTICE b/NOTICE index 09628ff..5dd1ec8 100644 --- a/NOTICE +++ b/NOTICE
@@ -24,3 +24,10 @@ Copyright 2017 The Cobalt Authors. All Rights Reserved. Licensed under the Apache License, Version 2.0 See https://cobalt.googlesource.com/cobalt/+/master/src/AUTHORS for the list of Cobalt authors. + +Code from ICU is: +Copyright 2016-2023 Unicode, Inc. +and +Copyright (c) 1995-2016 International Business Machines Corporation and others +All rights reserved. +Licensed under UNICODE LICENSE V3 and the ICU License from https://github.com/unicode-org/icu/blob/main/LICENSE
diff --git a/plugin/Cobalt.conf.in b/plugin/Cobalt.conf.in index 0bd2ef7..e8a1690 100644 --- a/plugin/Cobalt.conf.in +++ b/plugin/Cobalt.conf.in
@@ -19,7 +19,11 @@ advertisingid.add("ifa_type", "@PLUGIN_COBALT_IFA_TYPE@") advertisingid.add("lmt", "@PLUGIN_COBALT_LIMIT_AD_TRACKING@") -if boolean("@advertisingid@"): +if ( + "@PLUGIN_COBALT_ADVERTISING_ID@" or + "@PLUGIN_COBALT_IFA_TYPE@" or + "@PLUGIN_COBALT_LIMIT_AD_TRACKING@" +): configuration.add("advertisingid", advertisingid) systemproperties = JSON()
diff --git a/plugin/CobaltImplementation.cpp b/plugin/CobaltImplementation.cpp index 3be1428..a9ea8bb 100644 --- a/plugin/CobaltImplementation.cpp +++ b/plugin/CobaltImplementation.cpp
@@ -258,6 +258,7 @@ Block(); SbRdkQuit(); Wait(Thread::BLOCKED | Thread::STOPPED | Thread::STOPPING, Core::infinite); + std::quick_exit(0); } uint32_t Configure(PluginHost::IShell* service) {
diff --git a/plugin/CobaltJsonRpc.cpp b/plugin/CobaltJsonRpc.cpp index 2125e64..6a70cd7 100644 --- a/plugin/CobaltJsonRpc.cpp +++ b/plugin/CobaltJsonRpc.cpp
@@ -23,10 +23,6 @@ #include "Cobalt.h" #include "Module.h" -#ifndef SYSLOG_GLOBAL -#define SYSLOG_GLOBAL(CATEGORY, PARAMETERS) SYSLOG(CATEGORY, PARAMETERS) -#endif /* SYSLOG_GLOBAL */ - namespace WPEFramework { namespace Plugin { @@ -210,14 +206,14 @@ Exchange::IDictionary *dict( _cobalt->QueryInterface<Exchange::IDictionary>()); if (dict == nullptr) { - SYSLOG_GLOBAL(Logging::Error, (_T("IDictionary is not implemented"))); + SYSLOG(Logging::Error, (_T("IDictionary is not implemented"))); } else { std::string json; if (!dict->Get("settings", "accessibility", json)) { - SYSLOG_GLOBAL(Logging::Error, (_T("Cannot get 'accessibility' setting"))); + SYSLOG(Logging::Error, (_T("Cannot get 'accessibility' setting"))); } else if (!response.FromString(json)) { - SYSLOG_GLOBAL(Logging::Error, (_T("Cannot convert to JSON object"))); + SYSLOG(Logging::Error, (_T("Cannot convert to JSON object"))); } else { result = Core::ERROR_NONE; @@ -243,14 +239,14 @@ Exchange::IDictionary *dict( _cobalt->QueryInterface<Exchange::IDictionary>()); if (dict == nullptr) { - SYSLOG_GLOBAL(Logging::Error, (_T("IDictionary is not implemented"))); + SYSLOG(Logging::Error, (_T("IDictionary is not implemented"))); } else { std::string json; if (!param.ToString(json)) { - SYSLOG_GLOBAL(Logging::Error, (_T("Cannot convert to string"))); + SYSLOG(Logging::Error, (_T("Cannot convert to string"))); } else if (!dict->Set("settings", "accessibility", json)) { - SYSLOG_GLOBAL(Logging::Error, (_T("Cannot set 'accessibility' setting"))); + SYSLOG(Logging::Error, (_T("Cannot set 'accessibility' setting"))); } else { result = Core::ERROR_NONE;
diff --git a/plugin/Module.h b/plugin/Module.h index f0d8629..ec9c6d5 100644 --- a/plugin/Module.h +++ b/plugin/Module.h
@@ -24,5 +24,9 @@ #include <core/core.h> #include <plugins/plugins.h> +#if !defined(THUNDER_VERSION) && defined(THUNDER_VERSION_MAJOR) +#define THUNDER_VERSION THUNDER_VERSION_MAJOR +#endif + #undef EXTERNAL #define EXTERNAL
diff --git a/src/third_party/starboard/rdk/arm/configuration_constants.cc b/src/third_party/starboard/rdk/arm/configuration_constants.cc index b0fb96e..024605a 100644 --- a/src/third_party/starboard/rdk/arm/configuration_constants.cc +++ b/src/third_party/starboard/rdk/arm/configuration_constants.cc
@@ -158,8 +158,6 @@ // The maximum number of users that can be signed in at the same time. const uint32_t kSbUserMaxSignedIn = 1; -#if SB_API_VERSION >= 14 // Defines maximum space in bytes the cache directory kSbSystemPathCacheDirectory can // use. The default value is 24MiB. const uint32_t kSbMaxSystemPathCacheDirectorySize = 24 << 20; // 24MiB -#endif //SB_API_VERSION >= 14
diff --git a/src/third_party/starboard/rdk/arm/toolchain/BUILD.gn b/src/third_party/starboard/rdk/arm/toolchain/BUILD.gn index 84ef703..37c77e6 100644 --- a/src/third_party/starboard/rdk/arm/toolchain/BUILD.gn +++ b/src/third_party/starboard/rdk/arm/toolchain/BUILD.gn
@@ -30,15 +30,14 @@ import("//third_party/starboard/rdk/shared/build/rdk_toolchain.gni") -rdk_gcc_toolchain("host") { - envprefix = "BUILD_" - extra_ldflags = "" - toolchain_args = { - current_os = "linux" - current_cpu = "x86" - } -} - rdk_gcc_toolchain("target") { envprefix = "" } + +rdk_gcc_toolchain("native_target") { + envprefix = "" + toolchain_args = { + is_starboard = false + is_native_target_build = true + } +}
diff --git a/src/third_party/starboard/rdk/arm64/configuration_constants.cc b/src/third_party/starboard/rdk/arm64/configuration_constants.cc index b0fb96e..024605a 100644 --- a/src/third_party/starboard/rdk/arm64/configuration_constants.cc +++ b/src/third_party/starboard/rdk/arm64/configuration_constants.cc
@@ -158,8 +158,6 @@ // The maximum number of users that can be signed in at the same time. const uint32_t kSbUserMaxSignedIn = 1; -#if SB_API_VERSION >= 14 // Defines maximum space in bytes the cache directory kSbSystemPathCacheDirectory can // use. The default value is 24MiB. const uint32_t kSbMaxSystemPathCacheDirectorySize = 24 << 20; // 24MiB -#endif //SB_API_VERSION >= 14
diff --git a/src/third_party/starboard/rdk/arm64/toolchain/BUILD.gn b/src/third_party/starboard/rdk/arm64/toolchain/BUILD.gn index da593cb..37c77e6 100644 --- a/src/third_party/starboard/rdk/arm64/toolchain/BUILD.gn +++ b/src/third_party/starboard/rdk/arm64/toolchain/BUILD.gn
@@ -30,15 +30,14 @@ import("//third_party/starboard/rdk/shared/build/rdk_toolchain.gni") -rdk_gcc_toolchain("host") { - envprefix = "BUILD_" - extra_ldflags = "" - toolchain_args = { - current_os = "linux" - current_cpu = "x64" - } -} - rdk_gcc_toolchain("target") { envprefix = "" } + +rdk_gcc_toolchain("native_target") { + envprefix = "" + toolchain_args = { + is_starboard = false + is_native_target_build = true + } +}
diff --git a/src/third_party/starboard/rdk/rpi/configuration_constants.cc b/src/third_party/starboard/rdk/rpi/configuration_constants.cc index 6602c64..2b70460 100644 --- a/src/third_party/starboard/rdk/rpi/configuration_constants.cc +++ b/src/third_party/starboard/rdk/rpi/configuration_constants.cc
@@ -33,8 +33,6 @@ #include "starboard/configuration_constants.h" -#if SB_API_VERSION >= 12 - // Determines the threshhold of allocation size that should be done with mmap // (if available), rather than allocated within the core heap. const size_t kSbDefaultMmapThreshold = 256 * 1024U; @@ -161,9 +159,5 @@ // The maximum number of users that can be signed in at the same time. const uint32_t kSbUserMaxSignedIn = 1; -#endif // SB_API_VERSION >= 12 - -#if SB_API_VERSION >= 14 // The maximum size the cache directory is allowed to use in bytes. const uint32_t kSbMaxSystemPathCacheDirectorySize = 24 << 20; // 24MiB -#endif // SB_API_VERSION >= 14
diff --git a/src/third_party/starboard/rdk/rpi/toolchain/BUILD.gn b/src/third_party/starboard/rdk/rpi/toolchain/BUILD.gn index 84ef703..37c77e6 100644 --- a/src/third_party/starboard/rdk/rpi/toolchain/BUILD.gn +++ b/src/third_party/starboard/rdk/rpi/toolchain/BUILD.gn
@@ -30,15 +30,14 @@ import("//third_party/starboard/rdk/shared/build/rdk_toolchain.gni") -rdk_gcc_toolchain("host") { - envprefix = "BUILD_" - extra_ldflags = "" - toolchain_args = { - current_os = "linux" - current_cpu = "x86" - } -} - rdk_gcc_toolchain("target") { envprefix = "" } + +rdk_gcc_toolchain("native_target") { + envprefix = "" + toolchain_args = { + is_starboard = false + is_native_target_build = true + } +}
diff --git a/src/third_party/starboard/rdk/shared/BUILD.gn b/src/third_party/starboard/rdk/shared/BUILD.gn index 6dfbcbd..0f8d33e 100644 --- a/src/third_party/starboard/rdk/shared/BUILD.gn +++ b/src/third_party/starboard/rdk/shared/BUILD.gn
@@ -33,8 +33,7 @@ declare_args() { rdk_enable_securityagent = true rdk_enable_ocdm = true - rdk_enable_cryptography = true - rdk_enable_cbcs = false + rdk_enable_rfc_api = false } pkg_config("glib") { @@ -64,11 +63,9 @@ ] } -if (rdk_enable_cryptography) { - pkg_config("cryptography") { - packages = [ "WPEFrameworkCryptography" ] - defines = [ "HAS_CRYPTOGRAPHY=1" ] - } +pkg_config("cryptography") { + packages = [ "WPEFrameworkCryptography" ] + defines = [ "HAS_CRYPTOGRAPHY=1" ] } if (rdk_enable_securityagent) { @@ -88,48 +85,20 @@ static_library("starboard_platform") { check_includes = false + # has_pedantic_warnings = true + defines = [] sources = [ # Shared sources "//starboard/shared/gles/system_gles2.cc", - "//starboard/shared/iso/character_is_alphanumeric.cc", - "//starboard/shared/iso/character_is_digit.cc", - "//starboard/shared/iso/character_is_hex_digit.cc", - "//starboard/shared/iso/character_is_space.cc", - "//starboard/shared/iso/character_is_upper.cc", - "//starboard/shared/iso/character_to_lower.cc", - "//starboard/shared/iso/character_to_upper.cc", "//starboard/shared/iso/directory_close.cc", "//starboard/shared/iso/directory_get_next.cc", "//starboard/shared/iso/directory_open.cc", - "//starboard/shared/iso/double_absolute.cc", - "//starboard/shared/iso/double_exponent.cc", - "//starboard/shared/iso/double_floor.cc", - "//starboard/shared/iso/double_is_finite.cc", - "//starboard/shared/iso/double_is_nan.cc", "//starboard/shared/iso/memory_allocate_unchecked.cc", - "//starboard/shared/iso/memory_compare.cc", - "//starboard/shared/iso/memory_copy.cc", - "//starboard/shared/iso/memory_find_byte.cc", "//starboard/shared/iso/memory_free.cc", - "//starboard/shared/iso/memory_move.cc", "//starboard/shared/iso/memory_reallocate_unchecked.cc", - "//starboard/shared/iso/memory_set.cc", - "//starboard/shared/iso/string_compare.cc", - "//starboard/shared/iso/string_compare_all.cc", - "//starboard/shared/iso/string_find_character.cc", - "//starboard/shared/iso/string_find_last_character.cc", - "//starboard/shared/iso/string_find_string.cc", - "//starboard/shared/iso/string_get_length.cc", - "//starboard/shared/iso/string_get_length_wide.cc", - "//starboard/shared/iso/string_parse_double.cc", - "//starboard/shared/iso/string_parse_signed_integer.cc", - "//starboard/shared/iso/string_parse_uint64.cc", - "//starboard/shared/iso/string_parse_unsigned_integer.cc", "//starboard/shared/iso/string_scan.cc", - "//starboard/shared/iso/system_binary_search.cc", - "//starboard/shared/iso/system_sort.cc", "//starboard/shared/libevent/socket_waiter_add.cc", "//starboard/shared/libevent/socket_waiter_create.cc", "//starboard/shared/libevent/socket_waiter_destroy.cc", @@ -144,7 +113,6 @@ "//starboard/shared/linux/socket_get_interface_address.cc", "//starboard/shared/linux/system_get_random_data.cc", "//starboard/shared/linux/system_get_stack.cc", - "//starboard/shared/linux/system_get_total_cpu_memory.cc", "//starboard/shared/linux/system_get_used_cpu_memory.cc", "//starboard/shared/linux/system_is_debugger_attached.cc", "//starboard/shared/linux/thread_get_id.cc", @@ -211,7 +179,6 @@ "//starboard/shared/posix/storage_write_record.cc", "//starboard/shared/posix/string_compare_no_case.cc", "//starboard/shared/posix/string_compare_no_case_n.cc", - "//starboard/shared/posix/string_compare_wide.cc", "//starboard/shared/posix/string_format.cc", "//starboard/shared/posix/string_format_wide.cc", "//starboard/shared/posix/system_break_into_debugger.cc", @@ -226,7 +193,6 @@ "//starboard/shared/posix/time_get_now.cc", "//starboard/shared/posix/time_is_time_thread_now_supported.cc", "//starboard/shared/posix/time_zone_get_current.cc", - "//starboard/shared/posix/time_zone_get_name.cc", "//starboard/shared/pthread/condition_variable_broadcast.cc", "//starboard/shared/pthread/condition_variable_create.cc", "//starboard/shared/pthread/condition_variable_destroy.cc", @@ -298,24 +264,16 @@ "//starboard/shared/starboard/log_mutex.cc", "//starboard/shared/starboard/log_raw_format.cc", "//starboard/shared/starboard/media/media_can_play_mime_and_key_system.cc", - "//starboard/shared/starboard/media/media_get_audio_configuration_5_1.cc", "//starboard/shared/starboard/media/media_get_audio_output_count_single_audio_output.cc", - "//starboard/shared/starboard/media/mime_type.cc", "//starboard/shared/starboard/memory.cc", "//starboard/shared/starboard/queue_application.cc", - "//starboard/shared/starboard/string_concat.cc", - "//starboard/shared/starboard/string_concat_wide.cc", - "//starboard/shared/starboard/string_copy.cc", - "//starboard/shared/starboard/string_copy_wide.cc", "//starboard/shared/starboard/string_duplicate.cc", "//starboard/shared/starboard/system_get_random_uint64.cc", "//starboard/shared/starboard/system_request_blur.cc", "//starboard/shared/starboard/system_request_focus.cc", "//starboard/shared/starboard/system_request_freeze.cc", - "//starboard/shared/starboard/system_request_pause.cc", "//starboard/shared/starboard/system_request_reveal.cc", "//starboard/shared/starboard/system_request_stop.cc", - "//starboard/shared/starboard/system_request_unpause.cc", "//starboard/shared/starboard/system_supports_resume.cc", "//starboard/shared/starboard/window_set_default_options.cc", "//starboard/shared/stub/decode_target_get_info.cc", @@ -331,8 +289,6 @@ "//starboard/shared/stub/microphone_is_sample_rate_supported.cc", "//starboard/shared/stub/microphone_open.cc", "//starboard/shared/stub/microphone_read.cc", - "//starboard/shared/stub/system_get_total_gpu_memory.cc", - "//starboard/shared/stub/system_get_used_gpu_memory.cc", "//starboard/shared/stub/system_hide_splash_screen.cc", "//starboard/shared/stub/system_raise_platform_error.cc", "//starboard/shared/stub/system_symbolize.cc", @@ -376,6 +332,7 @@ "main_rdk.cc", "media/gst_media_utils.cc", "media/media_get_audio_buffer_budget.cc", + "media/media_get_audio_configuration.cc", "media/media_get_buffer_alignment.cc", "media/media_get_buffer_allocation_unit.cc", "media/media_get_buffer_garbage_collection_duration_threshold.cc", @@ -396,6 +353,7 @@ "platform_service.h", "player/player_create.cc", "player/player_destroy.cc", + "player/player_get_audio_configuration.cc", "player/player_get_current_frame.cc", "player/player_get_info.cc", "player/player_get_maximum_number_of_samples_per_write.cc", @@ -414,7 +372,6 @@ "speech/speech_synthesis_is_supported.cc", "speech/speech_synthesis_speak.cc", "system/system_egl.cc", - "system/system_get_connection_type.cc", "system/system_get_device_type.cc", "system/system_get_extensions.cc", "system/system_get_path.cc", @@ -422,8 +379,11 @@ "system/system_has_capability.cc", "system/system_network_is_disconnected.cc", "system/system_request_conceal.cc", - "system/system_request_suspend.cc", "system/system_sign_with_certification_secret_key.cc", + "system/system_get_total_cpu_memory.cc", + "system/system_get_total_gpu_memory.cc", + "system/system_get_used_gpu_memory.cc", + "time_zone_get_name.cc", "window/window_create.cc", "window/window_destroy.cc", "window/window_get_diagonal_size_in_inches.cc", @@ -435,13 +395,9 @@ if (target_platform == "rdk-rpi") { sources -= [ "//starboard/shared/gles/system_gles2.cc", - "//starboard/shared/starboard/media/media_get_audio_configuration_5_1.cc", - "//starboard/shared/starboard/media/media_get_audio_output_count_single_audio_output.cc", ] sources += [ "//starboard/raspi/shared/system_gles2.cc", - "//starboard/shared/starboard/media/media_get_audio_output_count_single_audio_output.cc", - "//starboard/shared/starboard/media/media_get_audio_configuration_stereo_only.cc", ] } @@ -465,18 +421,17 @@ ":glib", ":gstreamer", ":wpeframework", + ":cryptography", ] - if (rdk_enable_cryptography) { - configs += [ - ":cryptography", - ] + if (rdk_enable_rfc_api) { libs += [ "rfcapi", ] cflags += [ "-I=/usr/include/wdmp-c", ] + defines = [ "HAS_RFC_API=1" ] } if (rdk_enable_securityagent) { @@ -487,10 +442,6 @@ configs += [ ":ocdm" ] } - if (rdk_enable_cbcs) { - defines += [ "ENABLE_CBCS=1" ] - } - public_deps = [ "//starboard:starboard_headers_only", "//starboard/common", @@ -502,7 +453,10 @@ ] if (sb_is_evergreen_compatible) { - public_deps += [ "//starboard/elf_loader:evergreen_config" ] + public_deps += [ + "//starboard/elf_loader:constants", + "//starboard/elf_loader:evergreen_config" + ] deps += [ "//third_party/crashpad/wrapper" ] } else { deps += [ "//third_party/crashpad/wrapper:wrapper_stub" ]
diff --git a/src/third_party/starboard/rdk/shared/accessibility_get_caption_settings.cc b/src/third_party/starboard/rdk/shared/accessibility_get_caption_settings.cc index bfcdfb1..65817c8 100644 --- a/src/third_party/starboard/rdk/shared/accessibility_get_caption_settings.cc +++ b/src/third_party/starboard/rdk/shared/accessibility_get_caption_settings.cc
@@ -34,7 +34,6 @@ #include "third_party/starboard/rdk/shared/rdkservices.h" -#if SB_API_VERSION >= 12 || SB_HAS(CAPTIONS) bool SbAccessibilityGetCaptionSettings( SbAccessibilityCaptionSettings* caption_settings) { if (!caption_settings || @@ -45,4 +44,3 @@ return third_party::starboard::rdk::shared::Accessibility::GetCaptionSettings(caption_settings); } -#endif // SB_API_VERSION >= 12 || SB_HAS(CAPTIONS)
diff --git a/src/third_party/starboard/rdk/shared/accessibility_set_captions_enabled.cc b/src/third_party/starboard/rdk/shared/accessibility_set_captions_enabled.cc index 2297a47..5b7faa7 100644 --- a/src/third_party/starboard/rdk/shared/accessibility_set_captions_enabled.cc +++ b/src/third_party/starboard/rdk/shared/accessibility_set_captions_enabled.cc
@@ -30,8 +30,6 @@ #include "starboard/accessibility.h" #include "starboard/configuration.h" -#if SB_API_VERSION >= 12 || SB_HAS(CAPTIONS) bool SbAccessibilitySetCaptionsEnabled(bool enabled) { return false; } -#endif // SB_API_VERSION >= 12 || SB_HAS(CAPTIONS)
diff --git a/src/third_party/starboard/rdk/shared/application_rdk.cc b/src/third_party/starboard/rdk/shared/application_rdk.cc index 164a19b..cbfa0f7 100644 --- a/src/third_party/starboard/rdk/shared/application_rdk.cc +++ b/src/third_party/starboard/rdk/shared/application_rdk.cc
@@ -45,6 +45,7 @@ #include <sys/eventfd.h> #include <sys/timerfd.h> #include <unistd.h> +#include <malloc.h> namespace third_party { namespace starboard { @@ -95,8 +96,14 @@ } } +#if SB_API_VERSION >= 15 +Application::Application(SbEventHandleCallback sb_event_handle_callback) + : QueueApplication(sb_event_handle_callback) +#else Application::Application() - : input_handler_(new EssInput) + : QueueApplication() +#endif + , input_handler_(new EssInput) , hang_monitor_(new HangMonitor("Application")) { essos_context_recycle_ = !!getenv("COBALT_ESSOS_CONTEXT_DESTROY"); BuildEssosContext(); @@ -133,6 +140,8 @@ using ::starboard::shared::starboard::media::MimeSupportabilityCache; MimeSupportabilityCache::GetInstance()->SetCacheEnabled(true); KeySystemSupportabilityCache::GetInstance()->SetCacheEnabled(true); + + ScheduleMemoryUsageCheck(); } void Application::Teardown() { @@ -246,15 +255,9 @@ } void Application::Inject(Event* e) { -#if SB_API_VERSION >= 13 if (e && e->event && e->event->type == kSbEventTypeFreeze) { player::ForceStop(); } -#else - if (e && e->event && e->event->type == kSbEventTypeSuspend) { - player::ForceStop(); - } -#endif QueueApplication::Inject(e); } @@ -388,6 +391,48 @@ }, nullptr, 0); } +void Application::ReleaseMemory() { + Inject(new Event(kSbEventTypeLowMemory, NULL, [](void*) { + malloc_trim(0); + })); +} + +void Application::ScheduleMemoryUsageCheck(SbTime delay) { + SbEventSchedule([](void* data) { + SbTime back_off_timeout = Application::Get()->CheckMemoryUsage(); + if (back_off_timeout && back_off_timeout != kSbTimeMax) + Application::Get()->ScheduleMemoryUsageCheck(back_off_timeout); + }, nullptr, delay); +} + +SbTime Application::CheckMemoryUsage() { + static const int64_t kCPUMemoryPressureLimit = ([]() -> int64_t { + const char* env = std::getenv("COBALT_CPU_MEM_PRESSURE_IN_MB"); + int64_t limit_in_mb = SB_INT64_C(400); + if( env ) { + int64_t t = strtol(env, nullptr, 0); + if ( t >= 0 ) + limit_in_mb = t; + } + int64_t total_in_bytes = SbSystemGetTotalCPUMemory(); + return std::min(total_in_bytes, limit_in_mb * 1024 * 1024); + })(); + + if (!kCPUMemoryPressureLimit) + return kSbTimeMax; + + int64_t usage_in_bytes = SbSystemGetUsedCPUMemory(); + if (kCPUMemoryPressureLimit < usage_in_bytes) { + SB_LOG(INFO) << "Triggering memory pressure event. Current CPU mem. usage: " + << uint64_t(usage_in_bytes / 1024) << " kb, pressure limit: " + << uint64_t(kCPUMemoryPressureLimit / 1024) << " kb."; + ReleaseMemory(); + return 5 * kSbTimeSecond; + } + + return kSbTimeSecond; +} + } // namespace shared } // namespace rdk } // namespace starboard
diff --git a/src/third_party/starboard/rdk/shared/application_rdk.h b/src/third_party/starboard/rdk/shared/application_rdk.h index 909ee89..1bd3dda 100644 --- a/src/third_party/starboard/rdk/shared/application_rdk.h +++ b/src/third_party/starboard/rdk/shared/application_rdk.h
@@ -53,7 +53,11 @@ class Application : public ::starboard::shared::starboard::QueueApplication { public: +#if SB_API_VERSION >= 15 + explicit Application(SbEventHandleCallback sb_event_handle_callback); +#else Application(); +#endif // SB_API_VERSION >= 15 ~Application() override; static third_party::starboard::rdk::shared::Application* Get() { @@ -100,6 +104,10 @@ void BuildEssosContext(); void FatalError(); + void ScheduleMemoryUsageCheck(SbTime delay = kSbTimeSecond); + SbTime CheckMemoryUsage(); + void ReleaseMemory(); + static EssTerminateListener terminateListener; static EssKeyListener keyListener; static EssSettingsListener settingsListener;
diff --git a/src/third_party/starboard/rdk/shared/audio_sink/gstreamer_audio_sink_type.cc b/src/third_party/starboard/rdk/shared/audio_sink/gstreamer_audio_sink_type.cc index e1b5787..c78d6b1 100644 --- a/src/third_party/starboard/rdk/shared/audio_sink/gstreamer_audio_sink_type.cc +++ b/src/third_party/starboard/rdk/shared/audio_sink/gstreamer_audio_sink_type.cc
@@ -128,7 +128,7 @@ GstElement* audiosink_{nullptr}; GMainLoop* mainloop_{nullptr}; GMainContext* main_loop_context_{nullptr}; - guint source_id_{0}; + int source_id_{-1}; bool destroying_{false}; bool enough_data_{false}; std::string file_name_; @@ -193,7 +193,7 @@ appsrc_ = gst_element_factory_make("appsrc", "source"); GstAppSrcCallbacks callbacks = {&GStreamerAudioSink::AppSrcNeedData, &GStreamerAudioSink::AppSrcEnoughData, - nullptr}; + nullptr, nullptr}; gst_app_src_set_callbacks(GST_APP_SRC(appsrc_), &callbacks, this, nullptr); gst_app_src_set_max_bytes(GST_APP_SRC(appsrc_), kFramesPerRequest * GetBytesPerFrame());
diff --git a/src/third_party/starboard/rdk/shared/build/linux/BUILD.gn b/src/third_party/starboard/rdk/shared/build/linux/BUILD.gn new file mode 100644 index 0000000..f07772e --- /dev/null +++ b/src/third_party/starboard/rdk/shared/build/linux/BUILD.gn
@@ -0,0 +1,49 @@ +# Copyright 2023 The Cobalt Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright 2021 The Cobalt Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//third_party/starboard/rdk/shared/build/rdk_toolchain.gni") + +rdk_gcc_toolchain("x86") { + envprefix = "BUILD_" + extra_ldflags = "" + toolchain_args = { + current_os = "linux" + current_cpu = "x86" + } +} + +rdk_gcc_toolchain("x64") { + envprefix = "BUILD_" + extra_ldflags = "" + toolchain_args = { + current_os = "linux" + current_cpu = "x64" + } +}
diff --git a/src/third_party/starboard/rdk/shared/build/rdk_toolchain.gni b/src/third_party/starboard/rdk/shared/build/rdk_toolchain.gni index f533c5d..8f60930 100644 --- a/src/third_party/starboard/rdk/shared/build/rdk_toolchain.gni +++ b/src/third_party/starboard/rdk/shared/build/rdk_toolchain.gni
@@ -58,7 +58,7 @@ if (defined(invoker.toolchain_args)) { forward_variables_from(invoker.toolchain_args, "*") } -# is_clang = false + is_clang = false } } }
diff --git a/src/third_party/starboard/rdk/shared/configuration.cc b/src/third_party/starboard/rdk/shared/configuration.cc index 46edac4..070344c 100644 --- a/src/third_party/starboard/rdk/shared/configuration.cc +++ b/src/third_party/starboard/rdk/shared/configuration.cc
@@ -30,8 +30,8 @@ #include "third_party/starboard/rdk/shared/configuration.h" -#include "cobalt/extension/configuration.h" #include "starboard/common/configuration_defaults.h" +#include "starboard/extension/configuration.h" #include "third_party/starboard/rdk/shared/libcobalt.h" @@ -76,6 +76,7 @@ &::starboard::common::CobaltRasterizerTypeDefault, &::starboard::common::CobaltEnableJitDefault, &::starboard::common::CobaltFallbackSplashScreenTopicsDefault, + &::starboard::common::CobaltCanStoreCompiledJavascriptDefault, }; } // namespace
diff --git a/src/third_party/starboard/rdk/shared/drm/drm_system_ocdm.cc b/src/third_party/starboard/rdk/shared/drm/drm_system_ocdm.cc index 6a67de6..f33c652 100644 --- a/src/third_party/starboard/rdk/shared/drm/drm_system_ocdm.cc +++ b/src/third_party/starboard/rdk/shared/drm/drm_system_ocdm.cc
@@ -334,6 +334,11 @@ const char url[], const uint8_t challenge[], const uint16_t challenge_length) { + if (challenge_length == 0) { + Session::OnError(ocdm_session, user_data, "Empty challenge"); + return; + } + Session* session = static_cast<Session*>(user_data); std::string id; int ticket; @@ -750,28 +755,31 @@ if ( !g_ocdmGetMetricSystemData ) return nullptr; - int i = 1; - do { - uint32_t buffer_length = i * 4 * 1024; + const int kMaxRetry = 5; + for (int i = 0; i < kMaxRetry; ++i) { + uint32_t buffer_length = ( 1 << i ) * 4 * 1024; std::vector<uint8_t> tmp; tmp.resize(buffer_length); - auto rc = g_ocdmGetMetricSystemData(ocdm_system_, &buffer_length, tmp.data()); - if ( rc == ERROR_BUFFER_TOO_SMALL && ++i <= 4 ) { - continue; - } + const uint32_t kBufferTooSmallErrorCode = 4; // ERROR_BUFFER_TOO_SMALL + auto rc = g_ocdmGetMetricSystemData(ocdm_system_, &buffer_length, tmp.data()); if ( rc == ERROR_NONE ) { uint16_t out_length = (((buffer_length * 8) / 6) + 4) * sizeof(TCHAR); metrics_.resize(out_length, '\0'); out_length = WPEFramework::Core::URL::Base64Encode(tmp.data(), buffer_length, reinterpret_cast<char*>(metrics_.data()), out_length, false); metrics_.resize(out_length); - } else { - SB_LOG(ERROR) << "Failed to get drm metrics, rc = " << rc; + } else if ( rc == kBufferTooSmallErrorCode && i < (kMaxRetry - 1) ) { + SB_LOG(INFO) << "GetMetrics: buffer is too small, rc = " << rc << ", i = " << i; + continue; + } else { + metrics_.resize(0); + SB_LOG(ERROR) << "GetMetrics: failed, rc = " << rc; } - } while(false); + break; + } *size = static_cast<int>(metrics_.size()); return metrics_.data();
diff --git a/src/third_party/starboard/rdk/shared/drm/gst_decryptor_ocdm.cc b/src/third_party/starboard/rdk/shared/drm/gst_decryptor_ocdm.cc index 0f47544..3c4642a 100644 --- a/src/third_party/starboard/rdk/shared/drm/gst_decryptor_ocdm.cc +++ b/src/third_party/starboard/rdk/shared/drm/gst_decryptor_ocdm.cc
@@ -24,6 +24,7 @@ #include <gst/gst.h> #include <gst/base/gstbasetransform.h> +#include <gst/base/gstbytereader.h> #include <opencdm/open_cdm.h> @@ -130,9 +131,26 @@ gst_buffer_unmap(key, &map_info); } + uint32_t total_clear = 0; + uint32_t total_encrypted = 0; + GstMapInfo sample_map; + if (gst_buffer_map(subsamples, &sample_map, GST_MAP_READ)) { + GstByteReader* reader = gst_byte_reader_new(sample_map.data, sample_map.size); + for (uint32_t i = 0; i < subsample_count; ++i) { + uint16_t clear = 0; + uint32_t encrypted = 0; + gst_byte_reader_get_uint16_be(reader, &clear); + gst_byte_reader_get_uint32_be(reader, &encrypted); + total_clear += clear; + total_encrypted += encrypted; + } + gst_byte_reader_free(reader); + gst_buffer_unmap(subsamples, &sample_map); + } + GST_TRACE_OBJECT(self, "buf=(%" GST_PTR_FORMAT "), " - "subsample_count=%u, subsamples=(%p), iv=(%p), key=(%p : %s)", - buffer, subsample_count, subsamples, iv, key, md5sum); + "subsample_count=%u, subsamples=(%p), clear=%u, encrypted=%u, iv=(%p), key=(%p : %s)", + buffer, subsample_count, subsamples, total_clear, total_encrypted, iv, key, md5sum); g_free(md5sum); } @@ -230,7 +248,7 @@ } if ( rc != 0 ) { - if ( rc == ERROR_INVALID_SESSION ) { + if ( rc == (int)ERROR_INVALID_SESSION ) { GST_DEBUG_OBJECT(self, "Invalid session. Probably due to player shutdown."); return GST_BASE_TRANSFORM_FLOW_DROPPED; } @@ -432,14 +450,6 @@ const GValue* value = nullptr; -#if !(defined(ENABLE_CBCS) && ENABLE_CBCS) - const char* cipher_mode = gst_structure_get_string(info, "cipher-mode"); - if ( g_strcmp0(cipher_mode, "cbcs") == 0 ) { - GST_ELEMENT_ERROR (self, STREAM, DECRYPT, ("Decryption failed"), ("Unsupported chipher-mode = %s", cipher_mode)); - goto exit; - } -#endif - value = gst_structure_get_value(info, "kid"); if (!value) { GST_ELEMENT_ERROR (self, STREAM, DECRYPT_NOKEY, ("No key ID available for encrypted sample"), (NULL));
diff --git a/src/third_party/starboard/rdk/shared/ess_input.cc b/src/third_party/starboard/rdk/shared/ess_input.cc index 86feef8..24926e1 100644 --- a/src/third_party/starboard/rdk/shared/ess_input.cc +++ b/src/third_party/starboard/rdk/shared/ess_input.cc
@@ -355,6 +355,9 @@ case KEY_KPLEFTPAREN: return kSbKeyLaunchThisApplication; + case KEY_F8: + return kSbKeyMicrophone; + case KEY_UNKNOWN: break; } @@ -398,61 +401,6 @@ return kSbKeyModifiersNone; } -bool IsYouTubeCompliantKey(SbKey key) { - // Returns true if `key` is supported by YouTube apps. - // See 'Remote keys requirements' from - // https://developers.google.com/youtube/living-room/certification/software-certification-2023#remote-keys-and-events - // section: - // '8.1.2 Device remote keys not implemented by the YouTube application or reserved for device system functions MUST NOT dispatch any key event or key code.' - switch (key) { - case kSbKeyLeft: - case kSbKeyRight: - case kSbKeyUp: - case kSbKeyDown: - case kSbKeyReturn: - case kSbKeyEscape: - case kSbKeyPlay: - case kSbKeyPause: - case kSbKeyMediaPlayPause: - case kSbKeyMediaStop: - case kSbKeyMediaFastForward: - case kSbKeyMediaRewind: - case kSbKeySpace: - case kSbKeyBackspace: - case kSbKeyDelete: - case kSbKeyBrowserSearch: - case kSbKeyMicrophone: - case kSbKeyMediaPrevTrack: - case kSbKeyMediaNextTrack: - case kSbKeySubtitle: - case kSbKeyRed: - case kSbKeyGreen: - case kSbKeyYellow: - case kSbKeyBlue: - case kSbKeyLaunchThisApplication: - case kSbKey0: - case kSbKey1: - case kSbKey2: - case kSbKey3: - case kSbKey4: - case kSbKey5: - case kSbKey6: - case kSbKey7: - case kSbKey8: - case kSbKey9: - case kSbKeyChannelUp: - case kSbKeyChannelDown: - case kSbKeyLast: - case kSbKeyMediaAudioTrack: - case kSbKeyInfo: - case kSbKeyGuide: - return true; - default: - break; - } - return false; -} - } // namespace EssInput::EssInput() : key_repeat_interval_(kKeyHoldTime) { @@ -464,21 +412,13 @@ void EssInput::CreateKey(unsigned int key, SbInputEventType type, unsigned int modifiers, bool repeatable) { SbKey sb_key = KeyCodeToSbKey(key); - if (sb_key == kSbKeyUnknown) { - DeleteRepeatKey(); - return; - } - - if (!IsYouTubeCompliantKey(sb_key)) { - DeleteRepeatKey(); - return; - } + // if (sb_key == kSbKeyUnknown) { + // DeleteRepeatKey(); + // return; + // } SbInputData* data = new SbInputData(); memset(data, 0, sizeof(*data)); -#if SB_API_VERSION < 13 - data->timestamp = SbTimeGetMonotonicNow(); -#endif data->type = type; data->device_type = kSbInputDeviceTypeRemote; data->device_id = 1; // kKeyboardDeviceId;
diff --git a/src/third_party/starboard/rdk/shared/hang_detector.cc b/src/third_party/starboard/rdk/shared/hang_detector.cc index 74c5708..c3a5130 100644 --- a/src/third_party/starboard/rdk/shared/hang_detector.cc +++ b/src/third_party/starboard/rdk/shared/hang_detector.cc
@@ -39,7 +39,11 @@ namespace { -const uint32_t kMaxExpirationCount = 6; +#if defined(COBALT_BUILD_TYPE_GOLD) +const int32_t kMaxExpirationCount = 6; +#else +const int32_t kMaxExpirationCount = 18; +#endif pid_t get_tid() { #ifdef SYS_gettid
diff --git a/src/third_party/starboard/rdk/shared/libcobalt.cc b/src/third_party/starboard/rdk/shared/libcobalt.cc index 2fde63e..088d005 100644 --- a/src/third_party/starboard/rdk/shared/libcobalt.cc +++ b/src/third_party/starboard/rdk/shared/libcobalt.cc
@@ -61,83 +61,39 @@ Application::Get()->Link(link); } - void RequestSuspend() { + void RequestFreeze() { starboard::ScopedLock lock(mutex_); WaitForApp(lock); starboard::Semaphore sem; -#if SB_API_VERSION >= 13 Application::Get()->Freeze( &sem, [](void* ctx) { reinterpret_cast<starboard::Semaphore*>(ctx)->Put(); }); -#else - Application::Get()->Suspend( - &sem, - [](void* ctx) { - reinterpret_cast<starboard::Semaphore*>(ctx)->Put(); - }); -#endif sem.Take(); } - void RequestResume() { + void RequestFocus() { starboard::ScopedLock lock(mutex_); WaitForApp(lock); starboard::Semaphore sem; -#if SB_API_VERSION >= 13 Application::Get()->Focus( &sem, [](void* ctx) { reinterpret_cast<starboard::Semaphore*>(ctx)->Put(); }); -#else - Application::Get()->Unpause( - &sem, - [](void* ctx) { - reinterpret_cast<starboard::Semaphore*>(ctx)->Put(); - }); -#endif sem.Take(); } - void RequestPause() { + void RequestBlur() { starboard::ScopedLock lock(mutex_); WaitForApp(lock); starboard::Semaphore sem; -#if SB_API_VERSION >= 13 Application::Get()->Blur( &sem, [](void* ctx) { reinterpret_cast<starboard::Semaphore*>(ctx)->Put(); }); -#else - Application::Get()->Pause( - &sem, - [](void* ctx) { - reinterpret_cast<starboard::Semaphore*>(ctx)->Put(); - }); -#endif - sem.Take(); - } - - void RequestUnpause() { - starboard::ScopedLock lock(mutex_); - WaitForApp(lock); - starboard::Semaphore sem; -#if SB_API_VERSION >= 13 - Application::Get()->Focus( - &sem, - [](void* ctx) { - reinterpret_cast<starboard::Semaphore*>(ctx)->Put(); - }); -#else - Application::Get()->Unpause( - &sem, - [](void* ctx) { - reinterpret_cast<starboard::Semaphore*>(ctx)->Put(); - }); -#endif sem.Take(); } @@ -200,11 +156,7 @@ } if (should_invoke_default) { -#if SB_API_VERSION >= 13 Application::Get()->Conceal(NULL, NULL); -#else - Application::Get()->Suspend(NULL, NULL); -#endif } } @@ -279,19 +231,19 @@ } void SbRdkSuspend() { - GetContext()->RequestSuspend(); + GetContext()->RequestFreeze(); } void SbRdkResume() { - GetContext()->RequestResume(); + GetContext()->RequestFocus(); } void SbRdkPause() { - GetContext()->RequestPause(); + GetContext()->RequestBlur(); } void SbRdkUnpause() { - GetContext()->RequestUnpause(); + GetContext()->RequestFocus(); } void SbRdkQuit() {
diff --git a/src/third_party/starboard/rdk/shared/main_rdk.cc b/src/third_party/starboard/rdk/shared/main_rdk.cc index b7c5be9..8333a6c 100644 --- a/src/third_party/starboard/rdk/shared/main_rdk.cc +++ b/src/third_party/starboard/rdk/shared/main_rdk.cc
@@ -32,6 +32,7 @@ #include <gst/gst.h> #include <signal.h> +#include <sys/resource.h> #include "starboard/configuration.h" #include "starboard/shared/signal/crash_signals.h" @@ -41,6 +42,10 @@ #if SB_IS(EVERGREEN_COMPATIBLE) #include "third_party/crashpad/wrapper/wrapper.h" +#include "starboard/common/paths.h" +#include "starboard/elf_loader/elf_loader_constants.h" +#include "starboard/shared/starboard/command_line.h" +#include "starboard/shared/starboard/starboard_switches.h" #endif namespace third_party { @@ -55,7 +60,8 @@ } static void InstallStopSignalHandlers() { - struct sigaction action = {0}; + struct sigaction action; + memset (&action, 0, sizeof (action)); action.sa_handler = RequestStop; action.sa_flags = 0; ::sigemptyset(&action.sa_mask); @@ -73,10 +79,21 @@ } // namespace starboard } // namespace third_party +#if SB_API_VERSION >= 15 +int SbRunStarboardMain(int argc, char** argv, SbEventHandleCallback callback) { + third_party::starboard::rdk::shared::Application application(callback); + int result = application.Run(argc, argv); + return result; +} +#endif // SB_API_VERSION >= 15 extern "C" SB_EXPORT_PLATFORM int main(int argc, char** argv) { tzset(); + rlimit stack_size; + stack_size.rlim_cur = 512 * 1024; + setrlimit(RLIMIT_STACK, &stack_size); + GError* error = NULL; gst_init_check(NULL, NULL, &error); g_free(error); @@ -85,13 +102,27 @@ third_party::starboard::rdk::shared::InstallStopSignalHandlers(); #if SB_IS(EVERGREEN_COMPATIBLE) - third_party::crashpad::wrapper::InstallCrashpadHandler(true); + auto command_line = starboard::shared::starboard::CommandLine(argc, argv); + auto evergreen_content_path = + command_line.GetSwitchValue(starboard::elf_loader::kEvergreenContent); + std::string ca_certificates_path = evergreen_content_path.empty() + ? starboard::common::GetCACertificatesPath() + : starboard::common::GetCACertificatesPath(evergreen_content_path); + if (ca_certificates_path.empty()) { + SB_LOG(ERROR) << "Failed to get CA certificates path. Skip crashpad handler setup."; + } else { + third_party::crashpad::wrapper::InstallCrashpadHandler(true, ca_certificates_path); + } #endif int result = 0; { +#if SB_API_VERSION >= 15 + result = SbRunStarboardMain(argc, argv, SbEventHandle); +#else third_party::starboard::rdk::shared::Application application; result = application.Run(argc, argv); +#endif } third_party::starboard::rdk::shared::UninstallStopSignalHandlers();
diff --git a/src/third_party/starboard/rdk/shared/media/gst_media_utils.cc b/src/third_party/starboard/rdk/shared/media/gst_media_utils.cc index 934c5c8..0389442 100644 --- a/src/third_party/starboard/rdk/shared/media/gst_media_utils.cc +++ b/src/third_party/starboard/rdk/shared/media/gst_media_utils.cc
@@ -185,7 +185,12 @@ } std::vector<std::string> CodecToGstCaps(SbMediaAudioCodec codec, - const SbMediaAudioSampleInfo* info) { +#if SB_API_VERSION >= 15 + const SbMediaAudioStreamInfo* info +#else // SB_API_VERSION >= 15 + const SbMediaAudioSampleInfo* info +#endif +) { switch (codec) { default: case kSbMediaAudioCodecNone:
diff --git a/src/third_party/starboard/rdk/shared/media/gst_media_utils.h b/src/third_party/starboard/rdk/shared/media/gst_media_utils.h index fd8bb06..b343906 100644 --- a/src/third_party/starboard/rdk/shared/media/gst_media_utils.h +++ b/src/third_party/starboard/rdk/shared/media/gst_media_utils.h
@@ -32,7 +32,12 @@ bool GstRegistryHasElementForMediaType(SbMediaAudioCodec codec); std::vector<std::string> CodecToGstCaps( SbMediaAudioCodec codec, - const SbMediaAudioSampleInfo* info = nullptr); +#if SB_API_VERSION >= 15 + const SbMediaAudioStreamInfo* info = nullptr +#else // SB_API_VERSION >= 15 + const SbMediaAudioSampleInfo* info = nullptr +#endif +); std::vector<std::string> CodecToGstCaps(SbMediaVideoCodec codec); } // namespace media
diff --git a/src/third_party/starboard/rdk/shared/media/media_get_audio_buffer_budget.cc b/src/third_party/starboard/rdk/shared/media/media_get_audio_buffer_budget.cc index 0883d70..8e97e61 100644 --- a/src/third_party/starboard/rdk/shared/media/media_get_audio_buffer_budget.cc +++ b/src/third_party/starboard/rdk/shared/media/media_get_audio_buffer_budget.cc
@@ -33,8 +33,6 @@ #include "starboard/common/log.h" -#if SB_API_VERSION >= 10 int SbMediaGetAudioBufferBudget() { return 5 * 1024 * 1024; } -#endif // SB_API_VERSION >= 10
diff --git a/src/third_party/starboard/rdk/shared/system/system_request_suspend.cc b/src/third_party/starboard/rdk/shared/media/media_get_audio_configuration.cc similarity index 76% rename from src/third_party/starboard/rdk/shared/system/system_request_suspend.cc rename to src/third_party/starboard/rdk/shared/media/media_get_audio_configuration.cc index bd28584..fa47943 100644 --- a/src/third_party/starboard/rdk/shared/system/system_request_suspend.cc +++ b/src/third_party/starboard/rdk/shared/media/media_get_audio_configuration.cc
@@ -1,3 +1,4 @@ +// // Copyright 2020 Comcast Cable Communications Management, LLC // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,7 +15,7 @@ // // SPDX-License-Identifier: Apache-2.0 // -// Copyright 2017 The Cobalt Authors. All Rights Reserved. +// Copyright 2023 The Cobalt Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -28,13 +29,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "starboard/system.h" +#include "starboard/media.h" -#include "third_party/starboard/rdk/shared/libcobalt.h" +#include "third_party/starboard/rdk/shared/rdkservices.h" -#if SB_API_VERSION < 13 -void SbSystemRequestSuspend() { - // Route through conceal request. cobalt-plugin will call Suspend. - SbRdkRequestConceal(); +bool SbMediaGetAudioConfiguration( + int output_index, + SbMediaAudioConfiguration* out_configuration) { + return third_party::starboard::rdk::shared::DeviceInfo::GetAudioConfiguration(output_index, out_configuration); } -#endif // SB_API_VERSION < 13
diff --git a/src/third_party/starboard/rdk/shared/media/media_get_buffer_alignment.cc b/src/third_party/starboard/rdk/shared/media/media_get_buffer_alignment.cc index e27ba16..30025d6 100644 --- a/src/third_party/starboard/rdk/shared/media/media_get_buffer_alignment.cc +++ b/src/third_party/starboard/rdk/shared/media/media_get_buffer_alignment.cc
@@ -33,11 +33,6 @@ #include "starboard/common/log.h" -#if SB_API_VERSION >= 14 - int SbMediaGetBufferAlignment() { -#else // SB_API_VERSION >= 14 - int SbMediaGetBufferAlignment(SbMediaType type) { - SB_UNREFERENCED_PARAMETER(type); -#endif // SB_API_VERSION >= 10 +int SbMediaGetBufferAlignment() { return 1; }
diff --git a/src/third_party/starboard/rdk/shared/media/media_get_buffer_allocation_unit.cc b/src/third_party/starboard/rdk/shared/media/media_get_buffer_allocation_unit.cc index 8b0ce01..e046cc8 100644 --- a/src/third_party/starboard/rdk/shared/media/media_get_buffer_allocation_unit.cc +++ b/src/third_party/starboard/rdk/shared/media/media_get_buffer_allocation_unit.cc
@@ -33,8 +33,6 @@ #include "starboard/common/log.h" -#if SB_API_VERSION >= 10 int SbMediaGetBufferAllocationUnit() { return 1 * 1024 * 1024; } -#endif // SB_API_VERSION >= 10
diff --git a/src/third_party/starboard/rdk/shared/media/media_get_buffer_garbage_collection_duration_threshold.cc b/src/third_party/starboard/rdk/shared/media/media_get_buffer_garbage_collection_duration_threshold.cc index 9de47e0..4aa55ea 100644 --- a/src/third_party/starboard/rdk/shared/media/media_get_buffer_garbage_collection_duration_threshold.cc +++ b/src/third_party/starboard/rdk/shared/media/media_get_buffer_garbage_collection_duration_threshold.cc
@@ -33,8 +33,6 @@ #include "starboard/common/log.h" -#if SB_API_VERSION >= 10 SbTime SbMediaGetBufferGarbageCollectionDurationThreshold() { return 170 * kSbTimeSecond; } -#endif // SB_API_VERSION >= 10
diff --git a/src/third_party/starboard/rdk/shared/media/media_get_buffer_padding.cc b/src/third_party/starboard/rdk/shared/media/media_get_buffer_padding.cc index 242ba1d..c9a9df7 100644 --- a/src/third_party/starboard/rdk/shared/media/media_get_buffer_padding.cc +++ b/src/third_party/starboard/rdk/shared/media/media_get_buffer_padding.cc
@@ -14,13 +14,6 @@ // SPDX-License-Identifier: Apache-2.0 #include "starboard/media.h" -#include "starboard/common/log.h" - -#if SB_API_VERSION >= 14 - int SbMediaGetBufferPadding() { -#else // SB_API_VERSION >= 14 - int SbMediaGetBufferPadding(SbMediaType type) { - SB_UNREFERENCED_PARAMETER(type); -#endif // SB_API_VERSION >= 14 +int SbMediaGetBufferPadding() { return 0; }
diff --git a/src/third_party/starboard/rdk/shared/media/media_get_buffer_storage_type.cc b/src/third_party/starboard/rdk/shared/media/media_get_buffer_storage_type.cc index 58bed81..87456fd 100644 --- a/src/third_party/starboard/rdk/shared/media/media_get_buffer_storage_type.cc +++ b/src/third_party/starboard/rdk/shared/media/media_get_buffer_storage_type.cc
@@ -33,8 +33,6 @@ #include "starboard/common/log.h" -#if SB_API_VERSION >= 10 SbMediaBufferStorageType SbMediaGetBufferStorageType() { return kSbMediaBufferStorageTypeMemory; } -#endif // SB_API_VERSION >= 10
diff --git a/src/third_party/starboard/rdk/shared/media/media_get_initial_buffer_capacity.cc b/src/third_party/starboard/rdk/shared/media/media_get_initial_buffer_capacity.cc index fe673e0..9b86ca5 100644 --- a/src/third_party/starboard/rdk/shared/media/media_get_initial_buffer_capacity.cc +++ b/src/third_party/starboard/rdk/shared/media/media_get_initial_buffer_capacity.cc
@@ -17,8 +17,6 @@ #include "starboard/common/log.h" -#if SB_API_VERSION >= 10 int SbMediaGetInitialBufferCapacity() { return 21 * 1024 * 1024; } -#endif // SB_API_VERSION >= 10
diff --git a/src/third_party/starboard/rdk/shared/media/media_get_max_buffer_capacity.cc b/src/third_party/starboard/rdk/shared/media/media_get_max_buffer_capacity.cc index e4dea0c..ec383a7 100644 --- a/src/third_party/starboard/rdk/shared/media/media_get_max_buffer_capacity.cc +++ b/src/third_party/starboard/rdk/shared/media/media_get_max_buffer_capacity.cc
@@ -17,7 +17,6 @@ #include "starboard/common/log.h" -#if SB_API_VERSION >= 10 int SbMediaGetMaxBufferCapacity(SbMediaVideoCodec codec, int resolution_width, int resolution_height, @@ -45,4 +44,3 @@ // must be larger than sum of 8k video budget and non-video budget. return 360 * 1024 * 1024; } -#endif // SB_API_VERSION >= 10
diff --git a/src/third_party/starboard/rdk/shared/media/media_get_progressive_buffer_budget.cc b/src/third_party/starboard/rdk/shared/media/media_get_progressive_buffer_budget.cc index 933e8f1..2fca5fe 100644 --- a/src/third_party/starboard/rdk/shared/media/media_get_progressive_buffer_budget.cc +++ b/src/third_party/starboard/rdk/shared/media/media_get_progressive_buffer_budget.cc
@@ -18,7 +18,6 @@ #include "starboard/common/log.h" -#if SB_API_VERSION >= 10 int SbMediaGetProgressiveBufferBudget(SbMediaVideoCodec codec, int resolution_width, int resolution_height, @@ -29,4 +28,3 @@ SB_UNREFERENCED_PARAMETER(bits_per_pixel); return 12 * 1024 * 1024; } -#endif // SB_API_VERSION >= 10
diff --git a/src/third_party/starboard/rdk/shared/media/media_get_video_buffer_budget.cc b/src/third_party/starboard/rdk/shared/media/media_get_video_buffer_budget.cc index 496c2ea..ba5c00c 100644 --- a/src/third_party/starboard/rdk/shared/media/media_get_video_buffer_budget.cc +++ b/src/third_party/starboard/rdk/shared/media/media_get_video_buffer_budget.cc
@@ -16,7 +16,6 @@ #include "starboard/common/log.h" -#if SB_API_VERSION >= 10 int SbMediaGetVideoBufferBudget(SbMediaVideoCodec codec, int resolution_width, int resolution_height, @@ -50,4 +49,3 @@ // lower than 8k (7680x4320). return 300 * 1024 * 1024; } -#endif // SB_API_VERSION >= 10
diff --git a/src/third_party/starboard/rdk/shared/media/media_is_buffer_pool_allocate_on_demand.cc b/src/third_party/starboard/rdk/shared/media/media_is_buffer_pool_allocate_on_demand.cc index 1989f92..58e6a2d 100644 --- a/src/third_party/starboard/rdk/shared/media/media_is_buffer_pool_allocate_on_demand.cc +++ b/src/third_party/starboard/rdk/shared/media/media_is_buffer_pool_allocate_on_demand.cc
@@ -18,8 +18,6 @@ #include "starboard/common/log.h" -#if SB_API_VERSION >= 10 bool SbMediaIsBufferPoolAllocateOnDemand() { return true; } -#endif // SB_API_VERSION >= 10
diff --git a/src/third_party/starboard/rdk/shared/media/media_is_buffer_using_memory_pool.cc b/src/third_party/starboard/rdk/shared/media/media_is_buffer_using_memory_pool.cc index 0f1f0e9..c3baa24 100644 --- a/src/third_party/starboard/rdk/shared/media/media_is_buffer_using_memory_pool.cc +++ b/src/third_party/starboard/rdk/shared/media/media_is_buffer_using_memory_pool.cc
@@ -16,8 +16,6 @@ // SPDX-License-Identifier: Apache-2.0 #include "starboard/media.h" -#if SB_API_VERSION >= 10 bool SbMediaIsBufferUsingMemoryPool() { return true; } -#endif // SB_API_VERSION >= 10
diff --git a/src/third_party/starboard/rdk/shared/media/media_is_supported.cc b/src/third_party/starboard/rdk/shared/media/media_is_supported.cc index 930d5db..d6512ee 100644 --- a/src/third_party/starboard/rdk/shared/media/media_is_supported.cc +++ b/src/third_party/starboard/rdk/shared/media/media_is_supported.cc
@@ -31,11 +31,8 @@ #include <string> -#if SB_API_VERSION >= 13 -#include "starboard/shared/starboard/media/media_support_internal.h" -#endif - #include "starboard/media.h" +#include "starboard/shared/starboard/media/media_support_internal.h" #include "third_party/starboard/rdk/shared/drm/drm_system_ocdm.h" @@ -62,13 +59,8 @@ case kSbMediaVideoCodecVc1: return {}; -#if SB_API_VERSION < 11 - case kSbMediaVideoCodecVp10: - return {{"video/webm"}}; -#else // SB_API_VERSION < 11 case kSbMediaVideoCodecAv1: return {}; -#endif // SB_API_VERSION < 11 case kSbMediaVideoCodecVp8: case kSbMediaVideoCodecVp9:
diff --git a/src/third_party/starboard/rdk/shared/platform_configuration/BUILD.gn b/src/third_party/starboard/rdk/shared/platform_configuration/BUILD.gn index db89e5e..1727d9d 100644 --- a/src/third_party/starboard/rdk/shared/platform_configuration/BUILD.gn +++ b/src/third_party/starboard/rdk/shared/platform_configuration/BUILD.gn
@@ -60,6 +60,9 @@ cflags_cc += [ "-std=gnu++14", + "-Wno-literal-suffix", + # Generated by Audio Renderer and Audio Sink implementations. + "-Wno-reorder", ] if (is_qa || is_gold) { @@ -131,15 +134,31 @@ "-Wextra", "-Wunreachable-code", ] + if (!is_clang) { + cflags += [ + "-Wno-expansion-to-defined", + ] + } } config("no_pedantic_warnings") { if (!is_clang) { + cflags = [ + "-Wno-conversion", + "-Wno-deprecated-declarations", + "-Wno-ignored-qualifiers", + "-Wno-multichar", + "-Wno-sign-conversion", + "-Wno-unused-function", + "-Wno-unused-local-typedefs", + "-Wno-unused-parameter", + "-Wno-unused-variable", + "-Wno-unused-but-set-variable", + ] cflags_cc = [ - "-Wno-literal-suffix", "-Wno-deprecated-copy", "-Wno-invalid-offsetof", - "-Wno-ignored-qualifiers", + "-Wno-literal-suffix", "-Wno-pessimizing-move", ] } else {
diff --git a/src/third_party/starboard/rdk/shared/platform_configuration/configuration.gni b/src/third_party/starboard/rdk/shared/platform_configuration/configuration.gni index 3def42b..a1885b8 100644 --- a/src/third_party/starboard/rdk/shared/platform_configuration/configuration.gni +++ b/src/third_party/starboard/rdk/shared/platform_configuration/configuration.gni
@@ -32,8 +32,9 @@ cobalt_font_package = "limited" final_executable_type = "shared_library" +starboard_level_final_executable_type = "shared_library" -sb_api_version = 14 +sb_api_version = 15 sb_filter_based_player = false gl_type = "system_gles2" @@ -43,6 +44,9 @@ no_pedantic_warnings_config_path = "//third_party/starboard/rdk/shared/platform_configuration:no_pedantic_warnings" +pedantic_warnings_config_path = + "//third_party/starboard/rdk/shared/platform_configuration:pedantic_warnings" + speed_config_path = "//third_party/starboard/rdk/shared/platform_configuration:speed"
diff --git a/src/third_party/starboard/rdk/shared/platform_service.cc b/src/third_party/starboard/rdk/shared/platform_service.cc index a530e5d..d606bb4 100644 --- a/src/third_party/starboard/rdk/shared/platform_service.cc +++ b/src/third_party/starboard/rdk/shared/platform_service.cc
@@ -33,11 +33,11 @@ #include <memory> #include <string> -#include "cobalt/extension/platform_service.h" #include "starboard/common/log.h" #include "starboard/common/string.h" #include "starboard/configuration.h" #include "starboard/shared/starboard/application.h" +#include "starboard/extension/platform_service.h" #include "third_party/starboard/rdk/shared/firebolt/firebolt.h" #include "third_party/starboard/rdk/shared/log_override.h"
diff --git a/src/third_party/starboard/rdk/shared/player/player_create.cc b/src/third_party/starboard/rdk/shared/player/player_create.cc index 70d056b..36bdeb6 100644 --- a/src/third_party/starboard/rdk/shared/player/player_create.cc +++ b/src/third_party/starboard/rdk/shared/player/player_create.cc
@@ -48,9 +48,17 @@ return kSbPlayerInvalid; } - auto *max_video_capabilities = creation_param->video_sample_info.max_video_capabilities; - auto audio_codec = creation_param->audio_sample_info.codec; - auto video_codec = creation_param->video_sample_info.codec; + #if SB_API_VERSION >= 15 + const auto& audio_info = creation_param->audio_stream_info; + const auto& video_info = creation_param->video_stream_info; + #else + const auto& audio_info = creation_param->audio_sample_info; + const auto& video_info = creation_param->video_sample_info; + #endif + + auto *max_video_capabilities = video_info.max_video_capabilities; + auto audio_codec = audio_info.codec; + auto video_codec = video_info.codec; auto drm_system = creation_param->drm_system; auto output_mode = creation_param->output_mode; @@ -81,7 +89,7 @@ } std::unique_ptr<SbPlayerPrivate> player { new SbPlayerPrivate( - window, video_codec, audio_codec, drm_system, creation_param->audio_sample_info, + window, video_codec, audio_codec, drm_system, audio_info, max_video_capabilities, sample_deallocate_func, decoder_status_func, player_status_func, player_error_func, context, output_mode, provider) };
diff --git a/src/third_party/starboard/rdk/shared/system/system_request_suspend.cc b/src/third_party/starboard/rdk/shared/player/player_get_audio_configuration.cc similarity index 72% copy from src/third_party/starboard/rdk/shared/system/system_request_suspend.cc copy to src/third_party/starboard/rdk/shared/player/player_get_audio_configuration.cc index bd28584..5366f77 100644 --- a/src/third_party/starboard/rdk/shared/system/system_request_suspend.cc +++ b/src/third_party/starboard/rdk/shared/player/player_get_audio_configuration.cc
@@ -1,3 +1,4 @@ +// // Copyright 2020 Comcast Cable Communications Management, LLC // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,7 +15,7 @@ // // SPDX-License-Identifier: Apache-2.0 // -// Copyright 2017 The Cobalt Authors. All Rights Reserved. +// Copyright 2023 The Cobalt Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -28,13 +29,18 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "starboard/system.h" +#include "starboard/player.h" +#include "starboard/media.h" -#include "third_party/starboard/rdk/shared/libcobalt.h" +#include "third_party/starboard/rdk/shared/player/player_internal.h" -#if SB_API_VERSION < 13 -void SbSystemRequestSuspend() { - // Route through conceal request. cobalt-plugin will call Suspend. - SbRdkRequestConceal(); +#if SB_API_VERSION >= 15 + +bool SbPlayerGetAudioConfiguration( + SbPlayer player, + int index, + SbMediaAudioConfiguration* out_audio_configuration) { + return SbMediaGetAudioConfiguration(index, out_audio_configuration); } -#endif // SB_API_VERSION < 13 + +#endif // SB_API_VERSION >= 15
diff --git a/src/third_party/starboard/rdk/shared/player/player_get_info.cc b/src/third_party/starboard/rdk/shared/player/player_get_info.cc index e60239b..b4f0324 100644 --- a/src/third_party/starboard/rdk/shared/player/player_get_info.cc +++ b/src/third_party/starboard/rdk/shared/player/player_get_info.cc
@@ -32,12 +32,16 @@ #include "starboard/player.h" #include "third_party/starboard/rdk/shared/player/player_internal.h" -#if SB_API_VERSION >= 10 -void SbPlayerGetInfo2(SbPlayer player, SbPlayerInfo2* out_player_info) { +#if SB_API_VERSION >= 15 +void SbPlayerGetInfo(SbPlayer player, SbPlayerInfo* out_player_info) { + if (player == kSbPlayerInvalid) + return; player->player_->GetInfo(out_player_info); } -#else -void SbPlayerGetInfo(SbPlayer /*player*/, SbPlayerInfo* /*out_player_info*/) { - SB_NOTIMPLEMENTED(); +#else // SB_API_VERSION >= 15 +void SbPlayerGetInfo2(SbPlayer player, SbPlayerInfo2* out_player_info) { + if (player == kSbPlayerInvalid) + return; + player->player_->GetInfo(out_player_info); } -#endif // SB_API_VERSION >= 10 +#endif // SB_API_VERSION >= 15
diff --git a/src/third_party/starboard/rdk/shared/player/player_get_maximum_number_of_samples_per_write.cc b/src/third_party/starboard/rdk/shared/player/player_get_maximum_number_of_samples_per_write.cc index 33126e3..ffa7fcd 100644 --- a/src/third_party/starboard/rdk/shared/player/player_get_maximum_number_of_samples_per_write.cc +++ b/src/third_party/starboard/rdk/shared/player/player_get_maximum_number_of_samples_per_write.cc
@@ -33,9 +33,9 @@ #include "third_party/starboard/rdk/shared/player/player_internal.h" -#if SB_API_VERSION >= 10 int SbPlayerGetMaximumNumberOfSamplesPerWrite(SbPlayer player, SbMediaType /*sample_type*/) { + if (player == kSbPlayerInvalid) + return 0; return player->MaxNumberOfSamplesPerWrite(); } -#endif // SB_API_VERSION >= 10
diff --git a/src/third_party/starboard/rdk/shared/player/player_internal.cc b/src/third_party/starboard/rdk/shared/player/player_internal.cc index d3aeab1..daeabd4 100644 --- a/src/third_party/starboard/rdk/shared/player/player_internal.cc +++ b/src/third_party/starboard/rdk/shared/player/player_internal.cc
@@ -21,13 +21,15 @@ #include <math.h> #include <glib.h> +#include <gst/gst.h> #include <gst/app/gstappsrc.h> +#include <gst/audio/audio.h> #include <gst/audio/streamvolume.h> #include <gst/base/gstbytewriter.h> -#include <gst/gst.h> #include <gst/base/gstflowcombiner.h> #include <gst/video/video.h> #include <gst/base/gstbasetransform.h> +#include <gst/base/gstbaseparse.h> #include <map> #include <string> @@ -43,6 +45,7 @@ #include "starboard/time.h" #include "starboard/memory.h" #include "starboard/drm.h" +#include "starboard/common/log.h" #include "third_party/starboard/rdk/shared/media/gst_media_utils.h" #include "third_party/starboard/rdk/shared/hang_detector.h" #include "third_party/starboard/rdk/shared/drm/gst_decryptor_ocdm.h" @@ -73,14 +76,13 @@ GST_DEBUG_CATEGORY(cobalt_gst_player_debug); #define GST_CAT_DEFAULT cobalt_gst_player_debug -#if !defined(GST_HAS_HDR_SUPPORT) -#if GST_CHECK_VERSION(1, 18, 0) || (defined(__has_include) && __has_include("gstreamer-1.0/gst/video/video-hdr.h")) +#if !defined(GST_HAS_HDR_SUPPORT) && GST_CHECK_VERSION(1, 18, 0) #define GST_HAS_HDR_SUPPORT 1 #endif -#endif static void PrintGstCaps(GstCaps* caps); static GstElement* CreatePayloader(); +static GstElement* CreateGstElement(const gchar* factory_name, const gchar* name_format, ...) G_GNUC_PRINTF (2, 3); static GSourceFuncs SourceFunctions = { // prepare @@ -114,14 +116,9 @@ return flag->value; } -bool isRialtoEnabled() -{ +bool isRialtoEnabled() { static bool is_rialto_enabled = false; -#if __GNUC__ < 10 - static volatile gsize init = 0; -#else static gsize init = 0; -#endif if (g_once_init_enter (&init)) { GstElementFactory *factory = gst_element_factory_find("rialtomsevideosink"); @@ -138,11 +135,7 @@ bool enableNativeAudio() { static bool enable_native_audio = false; -#if __GNUC__ < 10 - static volatile gsize init = 0; -#else static gsize init = 0; -#endif if (g_once_init_enter (&init)) { GstElementFactory* factory = gst_element_factory_find("brcmaudiosink"); @@ -423,6 +416,7 @@ gst_app_src_set_emit_signals(GST_APP_SRC(appsrc), FALSE); gst_app_src_set_callbacks(GST_APP_SRC(appsrc), callbacks, user_data, nullptr); gst_app_src_set_max_bytes(GST_APP_SRC(appsrc), max_bytes); + gst_base_src_set_format(GST_BASE_SRC(appsrc), GST_FORMAT_TIME); GstCobaltSrc* src = GST_COBALT_SRC(element); gchar* name = g_strdup_printf("src_%u", src->priv->pad_number); @@ -437,7 +431,7 @@ } if (decryptor) { - GST_DEBUG("Injecting decryptor element %" GST_PTR_FORMAT, decryptor); + GST_DEBUG_OBJECT(element, "Injecting decryptor element %" GST_PTR_FORMAT, decryptor); gst_bin_add(GST_BIN(element), decryptor); gst_element_sync_state_with_parent(decryptor); @@ -446,7 +440,7 @@ } if (payloader) { - GST_DEBUG("Injecting payloader element %" GST_PTR_FORMAT, payloader); + GST_DEBUG_OBJECT(element, "Injecting payloader element %" GST_PTR_FORMAT, payloader); if (GST_IS_BASE_TRANSFORM(payloader)) { gst_base_transform_set_in_place(GST_BASE_TRANSFORM(payloader), TRUE); @@ -496,45 +490,6 @@ return GST_PAD_PROBE_OK; }, msg, [](gpointer data) { gst_message_unref(GST_MESSAGE(data)); }); -#if GST_CHECK_VERSION(1,18,0) - gst_pad_add_probe ( - pad, GST_PAD_PROBE_TYPE_EVENT_BOTH, - [](GstPad * pad, GstPadProbeInfo * info, gpointer data) -> GstPadProbeReturn { - GstEvent *event = GST_PAD_PROBE_INFO_EVENT(info); - GstSegment *segment = reinterpret_cast<GstSegment*>(data); - switch ( GST_EVENT_TYPE(event) ) { - case GST_EVENT_SEEK: - break; - case GST_EVENT_SEGMENT: { - const GstSegment *src = nullptr; - gst_event_parse_segment(event, &src); - gst_segment_copy_into(src, segment); - // fallthrough - } - default: - return GST_PAD_PROBE_OK; - }; - gdouble rate = 1.0; - GstSeekFlags flags = GST_SEEK_FLAG_NONE; - gst_event_parse_seek (event, &rate, NULL, &flags, NULL, NULL, NULL, NULL); - if ( !!(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE) ) { - gdouble rate_multiplier = rate / segment->rate; - GstEvent *rate_change_event = - gst_event_new_instant_rate_change(rate_multiplier, (GstSegmentFlags)flags); - gst_event_set_seqnum (rate_change_event, gst_event_get_seqnum (event)); - GstPad *peer_pad = gst_pad_get_peer(pad); - GST_DEBUG("Sending instant rate change pad: %" GST_PTR_FORMAT ", event: %" GST_PTR_FORMAT ", rate_multiplier: %.2f", - peer_pad, rate_change_event, rate_multiplier); - if ( gst_pad_send_event (peer_pad, rate_change_event) != TRUE ) - GST_PAD_PROBE_INFO_FLOW_RETURN(info) = GST_FLOW_NOT_SUPPORTED; - gst_object_unref(peer_pad); - gst_event_unref(event); - return GST_PAD_PROBE_HANDLED; - } - return GST_PAD_PROBE_OK; - }, gst_segment_new(), reinterpret_cast<GDestroyNotify>(gst_segment_free)); -#endif - // Allocation query can stall streaming thread if sent during pre-roll. // Drop the query since we don't use proposed allocation anyway. gst_pad_add_probe ( @@ -542,7 +497,7 @@ [](GstPad * pad, GstPadProbeInfo * info, gpointer data) -> GstPadProbeReturn { GstQuery* query = GST_PAD_PROBE_INFO_QUERY(info); if (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION) { - GST_DEBUG_OBJECT(pad, "Drop allocation query"); + GST_TRACE_OBJECT(pad, "Drop allocation query"); return GST_PAD_PROBE_DROP; } return GST_PAD_PROBE_OK; @@ -747,11 +702,7 @@ case kSbMediaTransferId12BitBt2020: return GST_VIDEO_TRANSFER_BT2020_12; case kSbMediaTransferIdSmpteSt2084: -#if GST_CHECK_VERSION(1, 18, 0) return GST_VIDEO_TRANSFER_SMPTE2084; -#else - return GST_VIDEO_TRANSFER_SMPTE_ST_2084; -#endif case kSbMediaTransferIdAribStdB67: return GST_VIDEO_TRANSFER_ARIB_STD_B67; case kSbMediaTransferIdUnspecified: @@ -799,9 +750,8 @@ GST_DEBUG ("Setting \"colorimetry\" to %s", tmp); g_free (tmp); } -#if GST_CHECK_VERSION(1, 18, 0) GstVideoMasteringDisplayInfo mastering_display_info; - gst_video_mastering_display_info_init (&mastering_display_info);// gst_video_mastering_display_metadata_init (&mastering_display_metadata); + gst_video_mastering_display_info_init (&mastering_display_info); mastering_display_info.display_primaries[0].x = (guint16)(color_metadata.mastering_metadata.primary_r_chromaticity_x * 50000); mastering_display_info.display_primaries[0].y = (guint16)(color_metadata.mastering_metadata.primary_r_chromaticity_y * 50000); @@ -819,41 +769,11 @@ gst_caps_set_simple (caps, "mastering-display-info", G_TYPE_STRING, tmp, NULL); GST_DEBUG ("Setting \"mastering-display-info\" to %s", tmp); g_free (tmp); -#else - GstVideoMasteringDisplayMetadata mastering_display_metadata; - gst_video_mastering_display_metadata_init (&mastering_display_metadata); - mastering_display_metadata.Rx = color_metadata.mastering_metadata.primary_r_chromaticity_x; - mastering_display_metadata.Ry = color_metadata.mastering_metadata.primary_r_chromaticity_y; - mastering_display_metadata.Gx = color_metadata.mastering_metadata.primary_g_chromaticity_x; - mastering_display_metadata.Gy = color_metadata.mastering_metadata.primary_g_chromaticity_y; - mastering_display_metadata.Bx = color_metadata.mastering_metadata.primary_b_chromaticity_x; - mastering_display_metadata.By = color_metadata.mastering_metadata.primary_b_chromaticity_y; - mastering_display_metadata.Wx = color_metadata.mastering_metadata.white_point_chromaticity_x; - mastering_display_metadata.Wy = color_metadata.mastering_metadata.white_point_chromaticity_y; - mastering_display_metadata.max_luma = color_metadata.mastering_metadata.luminance_max; - mastering_display_metadata.min_luma = color_metadata.mastering_metadata.luminance_min; - - if (gst_video_mastering_display_metadata_has_primaries(&mastering_display_metadata) && - gst_video_mastering_display_metadata_has_luminance(&mastering_display_metadata) ) { - gchar *tmp = - gst_video_mastering_display_metadata_to_caps_string - (&mastering_display_metadata); - gst_caps_set_simple (caps, "mastering-display-metadata", G_TYPE_STRING, tmp, NULL); - GST_DEBUG ("Setting \"mastering-display-metadata\" to %s", tmp); - g_free (tmp); - } -#endif if (color_metadata.max_cll && color_metadata.max_fall) { GstVideoContentLightLevel content_light_level; -#if GST_CHECK_VERSION(1, 18, 0) content_light_level.max_content_light_level = color_metadata.max_cll; content_light_level.max_frame_average_light_level = color_metadata.max_fall; gchar *tmp = gst_video_content_light_level_to_string(&content_light_level); -#else - content_light_level.maxCLL = color_metadata.max_cll; - content_light_level.maxFALL = color_metadata.max_fall; - gchar *tmp = gst_video_content_light_level_to_caps_string(&content_light_level); -#endif gst_caps_set_simple (caps, "content-light-level", G_TYPE_STRING, tmp, NULL); GST_DEBUG ("setting \"content-light-level\" to %s", tmp); g_free (tmp); @@ -867,7 +787,11 @@ return memcmp(&lhs, &rhs, sizeof(SbMediaColorMetadata)); } +#if SB_API_VERSION >= 15 +static void AddVideoInfoToGstCaps(const SbMediaVideoStreamInfo& info, GstCaps* caps) { +#else static void AddVideoInfoToGstCaps(const SbMediaVideoSampleInfo& info, GstCaps* caps) { +#endif AddColorMetadataToGstCaps(caps, info.color_metadata); gst_caps_set_simple (caps, "width", G_TYPE_INT, info.frame_width, @@ -881,17 +805,18 @@ } } -static void PrintPositionPerSink(GstElement* element) +static void PrintPositionPerSink(GstElement* element, GstDebugLevel level) { #ifndef GST_DISABLE_GST_DEBUG - if (gst_debug_category_get_threshold(GST_CAT_DEFAULT) < GST_LEVEL_INFO) + if (gst_debug_category_get_threshold(GST_CAT_DEFAULT) < level) return; #endif - auto fold_func = [](const GValue *vitem, GValue*, gpointer) -> gboolean { + auto fold_func = [](const GValue *vitem, GValue*, gpointer data) -> gboolean { + GstDebugLevel level = (GstDebugLevel)GPOINTER_TO_INT(data); GstObject *item = GST_OBJECT(g_value_get_object (vitem)); if (GST_IS_BIN (item)) { - PrintPositionPerSink(GST_ELEMENT(item)); + PrintPositionPerSink(GST_ELEMENT(item), level); } else if (GST_IS_BASE_SINK(item)) { GstElement* el = GST_ELEMENT(item); @@ -901,7 +826,8 @@ gst_query_parse_position(query, 0, &position); } gst_query_unref(query); - GST_INFO("Position from %s : %" GST_TIME_FORMAT, GST_ELEMENT_NAME(el), GST_TIME_ARGS(position)); + GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, level, el, + "Position from %s : %" GST_TIME_FORMAT, GST_ELEMENT_NAME(el), GST_TIME_ARGS(position)); } return TRUE; }; @@ -912,7 +838,7 @@ bool keep_going = true; while (keep_going) { GstIteratorResult ires; - ires = gst_iterator_fold (iter, fold_func, NULL, NULL); + ires = gst_iterator_fold (iter, fold_func, NULL, GINT_TO_POINTER(level)); switch (ires) { case GST_ITERATOR_RESYNC: gst_iterator_resync (iter); @@ -937,12 +863,7 @@ static GstElement* CreatePayloader() { static GstElementFactory* factory = nullptr; -#if __GNUC__ < 10 - static volatile gsize init = 0; -#else static gsize init = 0; -#endif - if (g_once_init_enter (&init)) { factory = gst_element_factory_find("svppay"); @@ -950,13 +871,26 @@ } if (!factory) { - GST_WARNING("svppay not found"); + GST_DEBUG("svppay not found"); return nullptr; } return gst_element_factory_create(factory, nullptr); } + +static GstElement* CreateGstElement(const gchar* factory_name, const gchar* name_format, ...) { + GstElement *result; + gchar *name; + va_list args; + va_start(args, name_format); + name = g_strdup_vprintf(name_format, args); + va_end(args); + result = gst_element_factory_make(factory_name, name); + g_free(name); + return result; +} + } // namespace // ********************************* Player ******************************** // @@ -1147,7 +1081,11 @@ SbMediaVideoCodec video_codec, SbMediaAudioCodec audio_codec, SbDrmSystem drm_system, - const SbMediaAudioSampleInfo& audio_sample_info, +#if SB_API_VERSION >= 15 + const SbMediaAudioStreamInfo& audio_info, +#else // SB_API_VERSION >= 15 + const SbMediaAudioSampleInfo& audio_info, +#endif const char* max_video_capabilities, SbPlayerDeallocateSampleFunc sample_deallocate_func, SbPlayerDecoderStatusFunc decoder_status_func, @@ -1166,11 +1104,17 @@ void SetVolume(double volume) override; void Seek(SbTime seek_to_timestamp, int ticket) override; bool SetRate(double rate) override; +#if SB_API_VERSION >= 15 + void GetInfo(SbPlayerInfo* info) override; +#else // SB_API_VERSION >= 15 void GetInfo(SbPlayerInfo2* info) override; +#endif void SetBounds(int zindex, int x, int y, int w, int h) override; GstElement* GetPipeline() const { return pipeline_; } bool IsValid() const { return SbThreadIsValid(playback_thread_); } + bool HasMaxVideoCaps() const { return !max_video_capabilities_.empty(); } + void AudioConfigurationChanged(); private: enum class State { @@ -1179,8 +1123,23 @@ kInitialPreroll, kPrerollAfterSeek, kPresenting, + kEnded, }; + static const char* PrivatePlayerStateToStr(State state) { +#define CASE(x) case x: return #x + switch(state) { + CASE(State::kNull); + CASE(State::kInitial); + CASE(State::kInitialPreroll); + CASE(State::kPrerollAfterSeek); + CASE(State::kPresenting); + CASE(State::kEnded); + } +#undef CASE + return "unknown"; + } + enum MediaTimestampIndex { kAudioIndex, kVideoIndex, @@ -1298,21 +1257,33 @@ SbTime MinTimestamp(MediaType* origin) const; void DecoderNeedsData(::starboard::ScopedLock&, MediaType media) const { - int need_data = static_cast<int>(media); - if (media != MediaType::kNone && (decoder_state_data_ & need_data) == need_data) { - GST_LOG("Already sent 'kSbPlayerDecoderStateNeedsData', ignoring new request"); + SB_DCHECK(media != MediaType::kNone); + + int need_data = static_cast<int>(media) & ~decoder_state_data_; + if (need_data == 0) { + GST_LOG_OBJECT(pipeline_, "Already sent 'kSbPlayerDecoderStateNeedsData' for media type: %d, ignoring new request", static_cast<int>(media)); return; } - if (media != MediaType::kNone && (eos_data_ & need_data) == need_data) { - GST_LOG("Stream(%d) already ended, ignoring needs data request", need_data); + if ((eos_data_ & need_data) == need_data) { + GST_LOG_OBJECT(pipeline_, "Stream(%d) already ended, ignoring needs data request", need_data); return; } + decoder_state_data_ |= need_data; + +#if 0 + if ((need_data & static_cast<int>(MediaType::kAudio)) != 0) + decoder_status_func_(player_, context_, kSbMediaTypeAudio, kSbPlayerDecoderStateNeedsData, ticket_); + if ((need_data & static_cast<int>(MediaType::kVideo)) != 0) + decoder_status_func_(player_, context_, kSbMediaTypeVideo, kSbPlayerDecoderStateNeedsData, ticket_); +#else DispatchOnWorkerThread(new DecoderStatusTask( decoder_status_func_, player_, ticket_, context_, - kSbPlayerDecoderStateNeedsData, media)); + kSbPlayerDecoderStateNeedsData, static_cast<MediaType>(need_data))); +#endif } + gboolean HandleBusMessage(GstBus* bus, GstMessage* message); void HandleApplicationMessage(GstBus* bus, GstMessage* message); void WritePendingSamples(); void CheckBuffering(gint64 position); @@ -1320,13 +1291,13 @@ void SchedulePlayingStateUpdate(); void AddBufferingProbe(GstClockTime target, int ticket); void HandleInititialSeek(::starboard::ScopedLock&); + void DidEnd(); SbPlayer player_; SbWindow window_; SbMediaVideoCodec video_codec_; SbMediaAudioCodec audio_codec_; SbDrmSystem drm_system_; - const SbMediaAudioSampleInfo audio_sample_info_; std::string max_video_capabilities_; SbPlayerDeallocateSampleFunc sample_deallocate_func_; SbPlayerDecoderStatusFunc decoder_status_func_; @@ -1343,7 +1314,7 @@ GstElement* pipeline_{nullptr}; int source_setup_id_{-1}; int bus_watch_id_{-1}; - SbThread playback_thread_; + SbThread playback_thread_ { kSbThreadInvalid }; ::starboard::Mutex mutex_; ::starboard::Mutex source_setup_mutex_; ::starboard::Mutex seek_mutex_; @@ -1420,6 +1391,25 @@ gst_object_unref(pipeline); } } + + bool CanCreate(const char* max_video_capabilities) { + #if !defined(COBALT_BUILD_TYPE_GOLD) + bool has_max_video_caps_set = (max_video_capabilities && *max_video_capabilities); + ::starboard::ScopedLock lock(mutex_); + for(const auto& p: players_) { + if (p->HasMaxVideoCaps() == has_max_video_caps_set) + return false; + } + #endif + return true; + } + + void AudioConfigurationChanged() { + ::starboard::ScopedLock lock(mutex_); + for(const auto& p: players_) { + p->AudioConfigurationChanged(); + } + } }; SB_ONCE_INITIALIZE_FUNCTION(PlayerRegistry, GetPlayerRegistry); @@ -1428,7 +1418,11 @@ SbMediaVideoCodec video_codec, SbMediaAudioCodec audio_codec, SbDrmSystem drm_system, - const SbMediaAudioSampleInfo& audio_sample_info, +#if SB_API_VERSION >= 15 + const SbMediaAudioStreamInfo& audio_info, +#else // SB_API_VERSION >= 15 + const SbMediaAudioSampleInfo& audio_info, +#endif const char* max_video_capabilities, SbPlayerDeallocateSampleFunc sample_deallocate_func, SbPlayerDecoderStatusFunc decoder_status_func, @@ -1442,7 +1436,6 @@ video_codec_(video_codec), audio_codec_(audio_codec), drm_system_(drm_system), - audio_sample_info_(audio_sample_info), sample_deallocate_func_(sample_deallocate_func), decoder_status_func_(decoder_status_func), player_status_func_(player_status_func), @@ -1466,18 +1459,20 @@ GstState state, pending; GstStateChangeReturn result = gst_element_get_state(player.pipeline_, &state, &pending, 0); gint64 position = player.GetPosition(); - GST_INFO("Player state: %s (pending: %s, result: %s), position: %" GST_TIME_FORMAT "", - gst_element_state_get_name(state), - gst_element_state_get_name(pending), - gst_element_state_change_return_get_name(result), - GST_TIME_ARGS(position)); + GST_INFO_OBJECT( + player.pipeline_, + "Player state: %s (pending: %s, result: %s), position: %" GST_TIME_FORMAT "", + gst_element_state_get_name(state), + gst_element_state_get_name(pending), + gst_element_state_change_return_get_name(result), + GST_TIME_ARGS(position)); player.hang_monitor_.Reset(); return G_SOURCE_CONTINUE; }, this, nullptr); hang_monitor_source_id_ = g_source_attach(src, main_loop_context_); g_source_unref(src); - GST_INFO("Creating player with max capabilities: %s", + GST_INFO_OBJECT(pipeline_,"Creating player with max capabilities: '%s'", max_video_capabilities); GstElementFactory* src_factory = gst_element_factory_find("cobaltsrc"); @@ -1488,7 +1483,10 @@ gst_object_unref(src_factory); } - pipeline_ = gst_element_factory_make("playbin", "media_pipeline"); + static int player_id = 0; + player_id++; + + pipeline_ = CreateGstElement("playbin", "media-pipeline-%d", player_id); unsigned flagAudio = getGstPlayFlag("audio"); unsigned flagVideo = getGstPlayFlag("video"); @@ -1523,15 +1521,15 @@ bus_watch_id_ = gst_bus_add_watch(bus, &PlayerImpl::BusMessageCallback, this); gst_object_unref(bus); - video_appsrc_ = gst_element_factory_make("appsrc", "vidsrc"); - audio_appsrc_ = gst_element_factory_make("appsrc", "audsrc"); + video_appsrc_ = CreateGstElement("appsrc", "vidsrc-%d", player_id); + audio_appsrc_ = CreateGstElement("appsrc", "audsrc-%d", player_id); GstElement* playsink = (gst_bin_get_by_name(GST_BIN(pipeline_), "playsink")); if (playsink) { g_object_set(G_OBJECT(playsink), "send-event-mode", 0, nullptr); g_object_unref(playsink); } else { - GST_WARNING("No playsink ?!?!?"); + GST_WARNING_OBJECT(pipeline_, "No playsink ?!?!?"); } if (drm_system_) { @@ -1545,6 +1543,9 @@ ChangePipelineState(GST_STATE_READY); g_main_context_pop_thread_default(main_loop_context_); + if (gst_element_get_state(pipeline_, nullptr, nullptr, 0) == GST_STATE_CHANGE_FAILURE) + return; + playback_thread_ = SbThreadCreate(0, kSbThreadPriorityRealTime, kSbThreadNoAffinity, true, "playback_thread", &PlayerImpl::ThreadEntryPoint, this); @@ -1592,31 +1593,32 @@ } g_main_loop_unref(main_loop_); g_main_context_unref(main_loop_context_); + GST_INFO_OBJECT(pipeline_, "BYE BYE player"); g_object_unref(pipeline_); - GST_INFO("BYE BYE player"); } // static gboolean PlayerImpl::BusMessageCallback(GstBus* bus, GstMessage* message, gpointer user_data) { - SB_UNREFERENCED_PARAMETER(bus); - PlayerImpl* self = static_cast<PlayerImpl*>(user_data); + return self->HandleBusMessage(bus, message); +} + +gboolean PlayerImpl::HandleBusMessage(GstBus* bus, GstMessage* message) { GST_TRACE("%d", SbThreadGetId()); + GST_LOG_OBJECT(pipeline_, "Got GST message '%s' from '%s'", GST_MESSAGE_TYPE_NAME(message), GST_MESSAGE_SRC_NAME(message)); switch (GST_MESSAGE_TYPE(message)) { case GST_MESSAGE_APPLICATION: { - self->HandleApplicationMessage(bus, message); + HandleApplicationMessage(bus, message); break; } case GST_MESSAGE_EOS: - if (GST_MESSAGE_SRC(message) == GST_OBJECT(self->pipeline_)) { - GST_INFO("EOS"); - self->DispatchOnWorkerThread(new PlayerStatusTask( - self->player_status_func_, self->player_, self->ticket_, - self->context_, kSbPlayerStateEndOfStream)); + if (GST_MESSAGE_SRC(message) == GST_OBJECT(pipeline_)) { + GST_INFO_OBJECT(pipeline_, "EOS"); + DidEnd(); } break; @@ -1626,25 +1628,23 @@ gst_message_parse_error(message, &err, &debug); std::string file_name = "cobalt_"; - file_name += (GST_OBJECT_NAME(self->pipeline_)); + file_name += (GST_OBJECT_NAME(pipeline_)); file_name += "_err_"; file_name += std::to_string(err->code); - GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(self->pipeline_), + GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(pipeline_), GST_DEBUG_GRAPH_SHOW_ALL, file_name.c_str()); - bool is_eos = (self->eos_data_ == (int)self->GetBothMediaTypeTakingCodecsIntoAccount()); + bool is_eos = (eos_data_ == (int)GetBothMediaTypeTakingCodecsIntoAccount()); if (err->domain == GST_STREAM_ERROR && is_eos) { - GST_WARNING("Got stream error. But all streams are ended, so reporting EOS. Error code %d: %s (%s).", + GST_WARNING_OBJECT(pipeline_, "Got stream error. But all streams are ended, so reporting EOS. Error code %d: %s (%s).", err->code, err->message, debug); - self->DispatchOnWorkerThread(new PlayerStatusTask( - self->player_status_func_, self->player_, self->ticket_, - self->context_, kSbPlayerStateEndOfStream)); + DidEnd(); } else { - GST_ERROR("Error %d: %s (%s)", err->code, err->message, debug); - self->DispatchOnWorkerThread(new PlayerErrorTask( - self->player_error_func_, self->player_, self->context_, + GST_ERROR_OBJECT(pipeline_, "Error %d: %s (%s)", err->code, err->message, debug); + DispatchOnWorkerThread(new PlayerErrorTask( + player_error_func_, player_, context_, kSbPlayerErrorDecode, err->message)); } g_free(debug); @@ -1653,7 +1653,7 @@ } case GST_MESSAGE_STATE_CHANGED: { - if (GST_MESSAGE_SRC(message) == GST_OBJECT(self->pipeline_)) { + if (GST_MESSAGE_SRC(message) == GST_OBJECT(pipeline_)) { GstState old_state, new_state, pending; gst_message_parse_state_changed(message, &old_state, &new_state, &pending); @@ -1663,16 +1663,16 @@ gst_element_state_get_name(new_state), gst_element_state_get_name(pending)); std::string file_name = "cobalt_"; - file_name += (GST_OBJECT_NAME(self->pipeline_)); + file_name += (GST_OBJECT_NAME(pipeline_)); file_name += "_"; file_name += gst_element_state_get_name(old_state); file_name += "_"; file_name += gst_element_state_get_name(new_state); - GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(self->pipeline_), + GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(pipeline_), GST_DEBUG_GRAPH_SHOW_ALL, file_name.c_str()); - if (GST_STATE(self->pipeline_) >= GST_STATE_PAUSED) { + if (GST_STATE(pipeline_) >= GST_STATE_PAUSED) { int ticket = 0; bool is_seek_pending = false; bool is_rate_pending = false; @@ -1680,93 +1680,93 @@ SbTime pending_seek_pos = kSbTimeMax; { - ::starboard::ScopedLock lock(self->mutex_); - ticket = self->ticket_; - is_seek_pending = self->is_seek_pending_; - is_rate_pending = self->pending_rate_ != .0; - pending_seek_pos = self->seek_position_; - SB_DCHECK(!is_seek_pending || self->seek_position_ != kSbTimeMax); - rate = self->pending_rate_; + ::starboard::ScopedLock lock(mutex_); + ticket = ticket_; + is_seek_pending = is_seek_pending_; + is_rate_pending = pending_rate_ != .0; + pending_seek_pos = seek_position_; + SB_DCHECK(!is_seek_pending || seek_position_ != kSbTimeMax); + rate = pending_rate_; if (is_seek_pending && is_rate_pending) { is_rate_pending = false; - self->rate_ = rate; - self->pending_rate_ = .0; + rate_ = rate; + pending_rate_ = .0; } - if (self->state_ == State::kPrerollAfterSeek || - self->state_ == State::kInitialPreroll) { - self->has_oob_write_pending_ |= is_seek_pending; + if (state_ == State::kPrerollAfterSeek || + state_ == State::kInitialPreroll) { + has_oob_write_pending_ |= is_seek_pending; } } - if (self->video_codec_ != kSbMediaVideoCodecNone && !self->pending_bounds_.IsEmpty()) { - PendingBounds bounds = self->pending_bounds_; - self->pending_bounds_ = {}; - self->SetBounds(0, bounds.x, bounds.y, bounds.w, bounds.h); + if (video_codec_ != kSbMediaVideoCodecNone && !pending_bounds_.IsEmpty()) { + PendingBounds bounds = pending_bounds_; + pending_bounds_ = {}; + SetBounds(0, bounds.x, bounds.y, bounds.w, bounds.h); } - if (is_rate_pending && GST_STATE(self->pipeline_) == GST_STATE_PLAYING) { - GST_INFO("Sending pending SetRate(rate=%lf)", rate); - self->SetRate(rate); + if (is_rate_pending && GST_STATE(pipeline_) == GST_STATE_PLAYING) { + GST_INFO_OBJECT(pipeline_,"Sending pending SetRate(rate=%lf)", rate); + SetRate(rate); } else if (is_seek_pending) { - GST_INFO("Sending pending Seek(position=%" PRId64 ", ticket=%d)", pending_seek_pos, ticket); - self->Seek(pending_seek_pos, ticket); + GST_INFO_OBJECT(pipeline_, "Sending pending Seek(position=%" PRId64 ", ticket=%d)", pending_seek_pos, ticket); + Seek(pending_seek_pos, ticket); } } } } break; case GST_MESSAGE_ASYNC_DONE: { - if (GST_MESSAGE_SRC(message) == GST_OBJECT(self->pipeline_)) { - GST_INFO("===> ASYNC-DONE %s %d", - gst_element_state_get_name(GST_STATE(self->pipeline_)), - static_cast<int>(self->state_)); + if (GST_MESSAGE_SRC(message) == GST_OBJECT(pipeline_)) { + GST_INFO_OBJECT(pipeline_, "===> ASYNC-DONE, pipeline state: %s, player state: %s", + gst_element_state_get_name(GST_STATE(pipeline_)), + PrivatePlayerStateToStr(state_)); - ::starboard::Mutex &mutex = self->mutex_; + ::starboard::Mutex &mutex = mutex_; ::starboard::ScopedLock lock(mutex); - if (self->state_ == State::kPrerollAfterSeek || - self->state_ == State::kInitialPreroll) { + if (state_ == State::kPrerollAfterSeek || + state_ == State::kInitialPreroll) { - bool is_seek_pending = self->is_seek_pending_; - bool has_pending_samples = (self->pending_samples_.empty() == false) || self->has_oob_write_pending_; + bool is_seek_pending = is_seek_pending_; + bool has_pending_samples = (pending_samples_.empty() == false) || has_oob_write_pending_; if (!is_seek_pending && has_pending_samples) { - int prev_has_data = static_cast<int>(self->has_enough_data_); - self->has_enough_data_ = static_cast<int>(MediaType::kBoth); + int prev_has_data = static_cast<int>(has_enough_data_); + has_enough_data_ = static_cast<int>(MediaType::kBoth); mutex.Release(); - GST_INFO("===> Writing pending samples"); - self->WritePendingSamples(); + GST_INFO_OBJECT(pipeline_, "===> Writing pending samples"); + WritePendingSamples(); mutex.Acquire(); - if (self->has_enough_data_ == static_cast<int>(MediaType::kBoth)) - self->has_enough_data_ = prev_has_data; - self->has_oob_write_pending_ = false; - self->pending_oob_write_condition_.Broadcast(); + if (has_enough_data_ == static_cast<int>(MediaType::kBoth)) + has_enough_data_ = prev_has_data; + has_oob_write_pending_ = false; + pending_oob_write_condition_.Broadcast(); } - GST_INFO("===> Asuming preroll done"); + GST_INFO_OBJECT(pipeline_, "===> Asuming preroll done"); // The below code is good but on BRCM the decoder reports old // position for some time which makes some YTLB 2020 test failing. - // self->seek_position_ = kSbTimeMax; - self->DispatchOnWorkerThread(new PlayerStatusTask( - self->player_status_func_, self->player_, self->ticket_, - self->context_, kSbPlayerStatePresenting)); - self->state_ = State::kPresenting; + // seek_position_ = kSbTimeMax; + DispatchOnWorkerThread(new PlayerStatusTask( + player_status_func_, player_, ticket_, + context_, kSbPlayerStatePresenting)); + state_ = State::kPresenting; } - self->SchedulePlayingStateUpdate(); + SchedulePlayingStateUpdate(); } } break; case GST_MESSAGE_CLOCK_LOST: - self->ChangePipelineState(GST_STATE_PAUSED); - self->ChangePipelineState(GST_STATE_PLAYING); + ChangePipelineState(GST_STATE_PAUSED); + ChangePipelineState(GST_STATE_PLAYING); break; case GST_MESSAGE_LATENCY: - gst_bin_recalculate_latency(GST_BIN(self->pipeline_)); + gst_bin_recalculate_latency(GST_BIN(pipeline_)); break; case GST_MESSAGE_QOS: { @@ -1780,22 +1780,20 @@ GstDebugLevel log_level = GST_LEVEL_DEBUG; gst_message_parse_qos_stats(message, &format, &processed, &dropped); if (format == GST_FORMAT_BUFFERS) { - ::starboard::ScopedLock lock(self->mutex_); - if (self->dropped_video_frames_ != static_cast<int>(dropped)) { + ::starboard::ScopedLock lock(mutex_); + if (dropped_video_frames_ != static_cast<int>(dropped)) { log_level = GST_LEVEL_INFO; - self->dropped_video_frames_ = static_cast<int>(dropped); + dropped_video_frames_ = static_cast<int>(dropped); } } GST_CAT_LEVEL_LOG ( - GST_CAT_DEFAULT, log_level, NULL, + GST_CAT_DEFAULT, log_level, pipeline_, "QOS written = %d, processed = %" G_GUINT64_FORMAT ", dropped = %" G_GUINT64_FORMAT, - self->total_video_frames_, processed, dropped); + total_video_frames_, processed, dropped); } } break; default: - GST_LOG("Got GST message %s from %s", GST_MESSAGE_TYPE_NAME(message), - GST_MESSAGE_SRC_NAME(message)); break; } @@ -1954,12 +1952,13 @@ // static void PlayerImpl::OnVideoBufferUnderflow(PlayerImpl* self) { - GST_WARNING("Decoder need data state = 0x%x," - " video appsrc level = %lld kb," - " audio appsrc level = %lld kb", - self->decoder_state_data_, - gst_app_src_get_current_level_bytes(GST_APP_SRC(self->video_appsrc_)) / 1024, - gst_app_src_get_current_level_bytes(GST_APP_SRC(self->audio_appsrc_)) / 1024); + GST_WARNING_OBJECT(self->pipeline_, + "Decoder need data state = 0x%x," + " video appsrc level = %" G_GUINT64_FORMAT " kb," + " audio appsrc level = %" G_GUINT64_FORMAT " kb", + self->decoder_state_data_, + gst_app_src_get_current_level_bytes(GST_APP_SRC(self->video_appsrc_)) / 1024, + gst_app_src_get_current_level_bytes(GST_APP_SRC(self->audio_appsrc_)) / 1024); } // static @@ -1970,12 +1969,12 @@ static bool disable_wait_video = !!getenv("COBALT_AML_DISABLE_WAIT_VIDEO"); bool has_video = (self->video_codec_ != kSbMediaVideoCodecNone); if (has_video && g_str_has_prefix(GST_ELEMENT_NAME(element), "amlhalasink") && !disable_wait_video) { - g_object_set(element, "wait-video", TRUE, "a-wait-timeout", 4000, nullptr); + g_object_set(element, "wait-video", TRUE, "a-wait-timeout", 4000, "disable-xrun", TRUE, nullptr); } else if (has_video && g_str_has_prefix(GST_ELEMENT_NAME(element), "westerossink")) { if (g_object_class_find_property(G_OBJECT_GET_CLASS(element), "zoom-mode")) { - GST_INFO("Setting westerossink zoom-mode to 0"); + GST_INFO_OBJECT(pipeline, "Setting westerossink zoom-mode to 0"); g_object_set(element, "zoom-mode", 0, nullptr); } g_signal_connect_swapped( @@ -1988,6 +1987,10 @@ } } + if (GST_IS_BASE_PARSE(element)) { + gst_base_parse_set_pts_interpolation(GST_BASE_PARSE(element), FALSE); + } + const gchar *klass_str = gst_element_class_get_metadata(GST_ELEMENT_GET_CLASS(element), "klass"); if (strstr(klass_str, "Sink")) { GObjectClass *oclass = G_OBJECT_GET_CLASS(element); @@ -2016,7 +2019,7 @@ src = audio_appsrc_; } - GST_DEBUG_OBJECT(src, "===> %d", SbThreadGetId()); + GST_INFO_OBJECT(src, "===> %d", SbThreadGetId()); ::starboard::ScopedLock lock(mutex_); if (state_ == State::kPrerollAfterSeek) GST_DEBUG_OBJECT(src, "===> Mark EOS with State::kPrerollAfterSeek"); @@ -2026,7 +2029,12 @@ else eos_data_ |= static_cast<int>(MediaType::kAudio); - gst_app_src_end_of_stream(GST_APP_SRC(src)); + if (eos_data_ == static_cast<int>(GetBothMediaTypeTakingCodecsIntoAccount())) { + if (audio_codec_ != kSbMediaAudioCodecNone) + gst_app_src_end_of_stream(GST_APP_SRC(audio_appsrc_)); + if (video_codec_ != kSbMediaVideoCodecNone) + gst_app_src_end_of_stream(GST_APP_SRC(video_appsrc_)); + } } bool PlayerImpl::WriteSample(SbMediaType sample_type, GstBuffer* buffer, uint64_t serial_id) { @@ -2102,16 +2110,44 @@ sample_deallocate_func_(player_, context_, sample_infos[0].buffer); return; } - GstClockTime timestamp = sample_infos[0].timestamp * kSbTimeNanosecondsPerMicrosecond; + +#if defined(SB_RDK_ZERO_COPY_SAMPLE_WRITE) && SB_RDK_ZERO_COPY_SAMPLE_WRITE + using BufferInfo = std::tuple<SbPlayerDeallocateSampleFunc, SbPlayer, void*, const void*>; + GstBuffer* buffer = + gst_buffer_new_wrapped_full( + static_cast<GstMemoryFlags>(0), + const_cast<gpointer> (sample_infos[0].buffer), + sample_infos[0].buffer_size, + 0, + sample_infos[0].buffer_size, + new BufferInfo(sample_deallocate_func_, player_, context_, sample_infos[0].buffer), + [](gpointer data) { + BufferInfo &info = *reinterpret_cast<BufferInfo*>(data); + auto deallocate_func = std::get<0>(info); + auto player = std::get<1>(info); + auto* context = std::get<2>(info); + const auto* buffer = std::get<3>(info); + deallocate_func(player, context, buffer); + delete &info; + }); +#else + G_GNUC_UNUSED gsize sz; GstBuffer* buffer = gst_buffer_new_allocate(nullptr, sample_infos[0].buffer_size, nullptr); - gsize sz = gst_buffer_fill(buffer, 0, sample_infos[0].buffer, sample_infos[0].buffer_size); + sz = gst_buffer_fill(buffer, 0, sample_infos[0].buffer, sample_infos[0].buffer_size); SB_DCHECK(sz == sample_infos[0].buffer_size); - GST_BUFFER_TIMESTAMP(buffer) = timestamp; sample_deallocate_func_(player_, context_, sample_infos[0].buffer); +#endif + + GstClockTime timestamp = sample_infos[0].timestamp * kSbTimeNanosecondsPerMicrosecond; + GST_BUFFER_TIMESTAMP(buffer) = timestamp; if (sample_infos[0].type == kSbMediaTypeVideo) { +#if SB_API_VERSION >= 15 + const auto& info = sample_infos[0].video_sample_info.stream_info; +#else const auto& info = sample_infos[0].video_sample_info; +#endif if (frame_width_ != info.frame_width || frame_height_ != info.frame_height || CompareColorMetadata(color_metadata_, info.color_metadata) != 0) { @@ -2128,15 +2164,21 @@ gst_caps_unref(gst_caps); } } - if (!info.is_key_frame) { + if (!sample_infos[0].video_sample_info.is_key_frame) { GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); } } - else { + else if (sample_infos[0].type == kSbMediaTypeAudio) { SB_DCHECK (sample_infos[0].type == kSbMediaTypeAudio); SB_DCHECK (audio_codec_ != kSbMediaAudioCodecNone); + if ( audio_caps_ == nullptr ) { - auto caps = CodecToGstCaps(audio_codec_, &audio_sample_info_); +#if SB_API_VERSION >= 15 + const auto& audio_info = sample_infos[0].audio_sample_info.stream_info; +#else + const auto& audio_info = sample_infos[0].audio_sample_info; +#endif + auto caps = CodecToGstCaps(audio_codec_, &audio_info); if (!caps.empty() && caps[0].c_str()) { GstCaps* gst_caps = gst_caps_from_string(caps[0].c_str()); PrintGstCaps(gst_caps); @@ -2145,12 +2187,31 @@ gst_caps_unref(gst_caps); } } + +#if SB_API_VERSION >= 15 + const guint64 kMaxGstClockTime = G_MAXUINT64 / G_GUINT64_CONSTANT (2); + const auto& info = sample_infos[0].audio_sample_info; + guint64 start_clip = 0, end_clip = 0; + + if (info.discarded_duration_from_front) + start_clip = (info.discarded_duration_from_front == kSbTimeMax) + ? kMaxGstClockTime : info.discarded_duration_from_front * kSbTimeNanosecondsPerMicrosecond; + + if (info.discarded_duration_from_back) + end_clip = (info.discarded_duration_from_back == kSbTimeMax) + ? kMaxGstClockTime : info.discarded_duration_from_back * kSbTimeNanosecondsPerMicrosecond; + + if (start_clip || end_clip) { + gst_buffer_add_audio_clipping_meta(buffer, GST_FORMAT_TIME, start_clip, end_clip); + GST_DEBUG_OBJECT(pipeline_, "Add audio clipping, start: %" PRIu64 ", end %" PRIu64, start_clip, end_clip); + } +#endif } RecordTimestamp(sample_type, timestamp); if (sample_infos[0].drm_info) { - GST_LOG("Encounterd encrypted %s sample", + GST_LOG_OBJECT(pipeline_, "Encounterd encrypted %s sample", sample_type == kSbMediaTypeVideo ? "video" : "audio"); SB_DCHECK(drm_system_); @@ -2166,7 +2227,7 @@ (encryption_scheme == kSbDrmEncryptionSchemeAesCtr) ? "cenc" : (encryption_scheme == kSbDrmEncryptionSchemeAesCbc ? "cbcs" : "unknown"); - GST_LOG("Encryption cipher-mode: %s", cipher_mode); + GST_LOG_OBJECT(pipeline_, "Encryption cipher-mode: %s", cipher_mode); key = gst_buffer_new_allocate( nullptr, sample_infos[0].drm_info->identifier_size, nullptr); @@ -2194,12 +2255,12 @@ if (!gst_byte_writer_put_uint16_be( &writer, sample_infos[0].drm_info->subsample_mapping[i].clear_byte_count)) - GST_ERROR("Failed writing clear subsample info at %d", i); + GST_ERROR_OBJECT(pipeline_, "Failed writing clear subsample info at %d", i); if (!gst_byte_writer_put_uint32_be(&writer, sample_infos[0] .drm_info->subsample_mapping[i] .encrypted_byte_count)) - GST_ERROR("Failed writing encrypted subsample info at %d", i); + GST_ERROR_OBJECT(pipeline_, "Failed writing encrypted subsample info at %d", i); } subsamples = gst_buffer_new_wrapped(subsamples_raw, subsamples_raw_size); } @@ -2229,7 +2290,7 @@ gst_buffer_unref(key); gst_buffer_unref(subsamples); } else { - GST_LOG("Encounterd clear %s sample", + GST_LOG_OBJECT(pipeline_, "Encounterd clear %s sample", sample_type == kSbMediaTypeVideo ? "video" : "audio"); } @@ -2246,15 +2307,15 @@ seek_pos_ns = seek_position_ * kSbTimeNanosecondsPerMicrosecond; } - if (GST_CLOCK_TIME_IS_VALID(seek_pos_ns) && seek_pos_ns > GST_BUFFER_TIMESTAMP(buffer)) { + if (GST_CLOCK_TIME_IS_VALID(seek_pos_ns) && GstClockTime(seek_pos_ns) > GST_BUFFER_TIMESTAMP(buffer)) { // Set dummy duration to let sink drop out-of-segment samples GST_BUFFER_DURATION (buffer) = GST_SECOND / 60; GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DECODE_ONLY); } if (keep_samples) { - GST_INFO("Pending flushing operation. Storing sample"); - GST_INFO("SampleType:%d %" GST_TIME_FORMAT " id:%" PRIu64 " b:%" GST_PTR_FORMAT, + GST_INFO_OBJECT(pipeline_, "Pending flushing operation. Storing sample"); + GST_INFO_OBJECT(pipeline_, "SampleType:%d %" GST_TIME_FORMAT " id:%" PRIu64 " b:%" GST_PTR_FORMAT, sample_type, GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)), serial, buffer); PendingSample sample(sample_type, buffer, serial); buffer= nullptr; @@ -2268,7 +2329,7 @@ while(has_oob_write_pending_) { const auto kWaitTime = 10 * kSbTimeSecond; if (!pending_oob_write_condition_.WaitTimed(kWaitTime)) { - GST_ERROR("Pending write took too long, give up"); + GST_ERROR_OBJECT(pipeline_, "Pending write took too long, give up"); has_oob_write_pending_ = false; break; } @@ -2283,7 +2344,7 @@ } if(local_samples.empty()) { - GST_WARNING("No pending samples"); + GST_WARNING_OBJECT(pipeline_, "No pending samples"); return; } @@ -2292,7 +2353,7 @@ SB_CHECK(sample.Type() == sample_type); if (serial != sample.SerialID()) { - GST_WARNING("Detected out-of-order sample. Expected serial: %" PRIu64 ", sample serial: %" PRIu64 "", + GST_WARNING_OBJECT(pipeline_, "Detected out-of-order sample. Expected serial: %" PRIu64 ", sample serial: %" PRIu64 "", serial, sample.SerialID()); } @@ -2312,7 +2373,7 @@ } } - GST_TRACE("Wrote sample."); + GST_LOG_OBJECT(pipeline_,"Wrote sample."); } void PlayerImpl::SetVolume(double volume) { @@ -2375,14 +2436,14 @@ DispatchOnWorkerThread(new PlayerStatusTask(player_status_func_, player_, ticket_, context_, kSbPlayerStatePrerolling)); AddBufferingProbe(position, ticket_); - GST_INFO("Successfully changed initial segment, position: %" GST_TIME_FORMAT ", ticket: %d", GST_TIME_ARGS(position), ticket_); + GST_INFO_OBJECT(pipeline_, "Successfully changed initial segment, position: %" GST_TIME_FORMAT ", ticket: %d", GST_TIME_ARGS(position), ticket_); return; } } #endif // Else send seek after pre-roll. - GST_INFO("Delaying seek."); + GST_INFO_OBJECT(pipeline_, "Delaying seek."); is_seek_pending_ = true; } @@ -2430,7 +2491,7 @@ } } - GST_DEBUG("Calling seek"); + GST_DEBUG_OBJECT(pipeline_, "Calling seek"); DispatchOnWorkerThread(new PlayerStatusTask(player_status_func_, player_, ticket_, context_, kSbPlayerStatePrerolling)); @@ -2448,7 +2509,7 @@ state_ = State::kPresenting; }, "Presenting after seek failure")); } else { - GST_DEBUG("Seek called with success"); + GST_DEBUG_OBJECT(pipeline_, "Seek called with success"); DispatchOnWorkerThread(new FunctionTask([this]() { state_ = State::kPrerollAfterSeek; }, "Preroll after seek")); @@ -2497,29 +2558,10 @@ need_instant_rate_change_ = ( rate != 1. ); mutex_.Release(); -#if GST_CHECK_VERSION(1,18,0) - static const bool kEnableInstantRateChangeSeek = ([]()->bool { - if( !!getenv("COBALT_DISABLE_INSTANT_RATE_CHANGE_SEEK") ) - return false; - if( !!getenv("COBALT_ENABLE_INSTANT_RATE_CHANGE_SEEK") ) - return true; - return false; - })(); - if (kEnableInstantRateChangeSeek) { - success = gst_element_seek( - pipeline_, rate, GST_FORMAT_TIME, - static_cast<GstSeekFlags>(GST_SEEK_FLAG_INSTANT_RATE_CHANGE), - GST_SEEK_TYPE_NONE, 0, - GST_SEEK_TYPE_NONE, 0); - } - else -#endif - { - GstStructure* s = gst_structure_new( + GstStructure* s = gst_structure_new( kCustomInstantRateChangeEventName, "rate", G_TYPE_DOUBLE, rate, NULL); - success = gst_element_send_event( + success = gst_element_send_event( pipeline_, gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM_OOB, s)); - } mutex_.Acquire(); } @@ -2533,25 +2575,22 @@ return success; } +#if SB_API_VERSION >= 15 +void PlayerImpl::GetInfo(SbPlayerInfo* out_player_info) { +#else // SB_API_VERSION >= 15 void PlayerImpl::GetInfo(SbPlayerInfo2* out_player_info) { - gint64 duration = 0; - if (gst_element_query_duration(pipeline_, GST_FORMAT_TIME, &duration) && - GST_CLOCK_TIME_IS_VALID(duration)) { - out_player_info->duration = duration; - } else { - out_player_info->duration = SB_PLAYER_NO_DURATION; - } +#endif // SB_API_VERSION >= 15 gint64 position = GetPosition(); CheckBuffering(position); - GST_TRACE("Position: %" GST_TIME_FORMAT " (Seek to: %" GST_TIME_FORMAT - ") Duration: %" GST_TIME_FORMAT, - GST_TIME_ARGS(position), - GST_TIME_ARGS(seek_position_ * kSbTimeNanosecondsPerMicrosecond), - GST_TIME_ARGS(duration)); + GST_LOG_OBJECT( + pipeline_,"Current position: %" GST_TIME_FORMAT " (Seek position: %" GST_TIME_FORMAT ")", + GST_TIME_ARGS(position), + GST_TIME_ARGS(seek_position_ != kSbTimeMax ? seek_position_ * kSbTimeNanosecondsPerMicrosecond : GST_CLOCK_TIME_NONE)); + out_player_info->duration = SB_PLAYER_NO_DURATION; out_player_info->current_media_timestamp = GST_CLOCK_TIME_IS_VALID(position) ? position / kSbTimeNanosecondsPerMicrosecond @@ -2570,14 +2609,17 @@ out_player_info->dropped_video_frames = dropped_video_frames_; } - GST_LOG("Frames dropped: %d, Frames corrupted: %d", - out_player_info->dropped_video_frames, - out_player_info->corrupted_video_frames); + GST_LOG_OBJECT( + pipeline_, + "Frames dropped: %d, Frames corrupted: %d", + out_player_info->dropped_video_frames, + out_player_info->corrupted_video_frames); + out_player_info->playback_rate = rate_; } void PlayerImpl::SetBounds(int zindex, int x, int y, int w, int h) { - GST_TRACE("Set Bounds: %d %d %d %d %d", zindex, x, y, w, h); + GST_TRACE_OBJECT(pipeline_, "Set Bounds: %d %d %d %d %d", zindex, x, y, w, h); GstElement* vid_sink = nullptr; g_object_get(pipeline_, "video-sink", &vid_sink, nullptr); if (vid_sink && g_object_class_find_property(G_OBJECT_GET_CLASS(vid_sink), @@ -2601,7 +2643,7 @@ GstState current, pending; current = pending = GST_STATE_VOID_PENDING; gst_element_get_state(pipeline_, ¤t, &pending, 0); - if ((current == state && pending == GST_STATE_VOID_PENDING) || pending == state) { + if (current == state || pending == state) { GST_DEBUG_OBJECT( pipeline_, "Rejected state change to %s from %s with %s pending", gst_element_state_get_name(state), @@ -2626,7 +2668,7 @@ GST_INFO_OBJECT(pipeline_, "Ignore state change to playing: invalid min sample ts"); return false; } - else if (seek_pos_ns > min_ts) { + else if (seek_pos_ns > GstClockTime(min_ts)) { GST_INFO_OBJECT( pipeline_, "Ignore state change to playing: no samples for seek time yet" @@ -2646,7 +2688,15 @@ } GST_INFO_OBJECT(pipeline_, "Changing state to %s", gst_element_state_get_name(state)); - return gst_element_set_state(pipeline_, state) != GST_STATE_CHANGE_FAILURE; + bool result = gst_element_set_state(pipeline_, state) != GST_STATE_CHANGE_FAILURE; + if (!result) { + GST_ERROR_OBJECT( + pipeline_, "Failed to change pipeline state to %s from %s with %s pending", + gst_element_state_get_name(state), + gst_element_state_get_name(current), + gst_element_state_get_name(pending)); + } + return result; } void PlayerImpl::CheckBuffering(gint64 position) { @@ -2654,7 +2704,7 @@ return; constexpr SbTime kMarginNs = - 350 * kSbTimeMillisecond * kSbTimeNanosecondsPerMicrosecond; + 50 * kSbTimeMillisecond * kSbTimeNanosecondsPerMicrosecond; MediaType origin = MediaType::kNone; SbTime min_ts = MinTimestamp(&origin); @@ -2671,12 +2721,9 @@ DecoderNeedsData(lock, origin); buf_target_min_ts_ = min_ts + kMarginNs; } - - PrintPositionPerSink(pipeline_); - GST_WARNING("Force setting to PAUSED. Pos: %" GST_TIME_FORMAT - " sample:%" GST_TIME_FORMAT, - GST_TIME_ARGS(position), GST_TIME_ARGS(min_ts + kMarginNs)); - + PrintPositionPerSink(pipeline_, GST_LEVEL_INFO); + GST_INFO_OBJECT(pipeline_, "Pause for buffering. Pos: %" GST_TIME_FORMAT + ", min ts:%" GST_TIME_FORMAT, GST_TIME_ARGS(position), GST_TIME_ARGS(min_ts)); ChangePipelineState(GST_STATE_PAUSED); } else if (buf_target_min_ts_ != kSbTimeMax && min_ts > buf_target_min_ts_) { double rate; @@ -2689,8 +2736,9 @@ GstState state, pending; gst_element_get_state(pipeline_, &state, &pending, 0); if (rate > .0 && state != GST_STATE_PLAYING && pending != GST_STATE_PLAYING) { - GST_TRACE("Moving to playing, min_ts = %" GST_TIME_FORMAT " need %" GST_TIME_FORMAT, - GST_TIME_ARGS(min_ts), GST_TIME_ARGS(buf_target_min_ts)); + GST_INFO_OBJECT( + pipeline_, "Resuming playback. min_ts: %" GST_TIME_FORMAT ", buff traget: %" GST_TIME_FORMAT, + GST_TIME_ARGS(min_ts), GST_TIME_ARGS(buf_target_min_ts)); ChangePipelineState(GST_STATE_PLAYING); } } @@ -2733,13 +2781,14 @@ if (GST_CLOCK_TIME_IS_VALID(cached_position_ns_) && std::abs(position - cached_position_ns_) > GST_SECOND) { - PrintPositionPerSink(pipeline_); - GST_WARNING("Unexpected position! More than 1 second jump detected: " + PrintPositionPerSink(pipeline_, GST_LEVEL_WARNING); + GST_WARNING_OBJECT(pipeline_, "Unexpected position! More than 1 second jump detected: " "%" GST_TIME_FORMAT " --> %" GST_TIME_FORMAT "", GST_TIME_ARGS(cached_position_ns_), GST_TIME_ARGS(position)); } + PrintPositionPerSink(pipeline_, GST_LEVEL_LOG); cached_position_ns_ = position; return position; } @@ -2766,16 +2815,16 @@ auto &prev_ts = prev_timestamps[sample.Type() == kSbMediaTypeVideo ? kVideoIndex : kAudioIndex]; if (prev_ts == sample.Timestamp()) { - GST_WARNING("Skipping %" GST_TIME_FORMAT ". Already written.", + GST_WARNING_OBJECT(pipeline_, "Skipping %" GST_TIME_FORMAT ". Already written.", GST_TIME_ARGS(prev_ts)); continue; } GstBuffer* buffer = keep_samples ? sample.CopyBuffer() : sample.TakeBuffer(); - GST_INFO("Writing pending: SampleType:%d id:%" PRIu64 " b:%" GST_PTR_FORMAT, sample.Type(), sample.SerialID(), buffer); + GST_INFO_OBJECT(pipeline_, "Writing pending: SampleType:%d id:%" PRIu64 " b:%" GST_PTR_FORMAT, sample.Type(), sample.SerialID(), buffer); prev_ts = GST_BUFFER_TIMESTAMP(buffer); if (WriteSample(sample.Type(), buffer, sample.SerialID())) { - GST_INFO("Pending sample was written."); + GST_INFO_OBJECT(pipeline_, "Pending sample was written."); } else { gst_buffer_unref(buffer); } @@ -2792,9 +2841,9 @@ } } if (keep_samples) { - GST_INFO("Stored samples again."); + GST_INFO_OBJECT(pipeline_, "Stored samples again."); } else { - GST_INFO("Seek ticket changed (%d -> %d), dropped local samples.", ticket, ticket_); + GST_INFO_OBJECT(pipeline_, "Seek ticket changed (%d -> %d), dropped local samples.", ticket, ticket_); } } } @@ -2848,7 +2897,7 @@ void PlayerImpl::HandleApplicationMessage(GstBus* bus, GstMessage* message) { const GstStructure* structure = gst_message_get_structure(message); if (gst_structure_has_name(structure, "force-stop") && !force_stop_) { - GST_INFO("Received force STOP, pipeline = %p!!!", pipeline_); + GST_INFO_OBJECT(pipeline_, "Received force STOP, pipeline = %p!!!", pipeline_); force_stop_ = true; ChangePipelineState(GST_STATE_READY); g_signal_handlers_disconnect_by_func(pipeline_, reinterpret_cast<gpointer>(&PlayerImpl::SetupSource), this); @@ -2862,7 +2911,7 @@ } else if (gst_structure_has_name(structure, kDidReceiveFirstSegmentMsgName)) { if (GST_MESSAGE_SRC(message) == GST_OBJECT(audio_appsrc_) || GST_MESSAGE_SRC(message) == GST_OBJECT(video_appsrc_)) { - GST_INFO("Received '%s' message from %" GST_PTR_FORMAT, kDidReceiveFirstSegmentMsgName, GST_MESSAGE_SRC(message)); + GST_INFO_OBJECT(pipeline_, "Received '%s' message from %" GST_PTR_FORMAT, kDidReceiveFirstSegmentMsgName, GST_MESSAGE_SRC(message)); bool should_set_rate = false; double rate = 0.; auto type = GST_MESSAGE_SRC(message) == GST_OBJECT(audio_appsrc_) ? MediaType::kAudio : MediaType::kVideo; @@ -2874,7 +2923,7 @@ mutex_.Release(); if (should_set_rate) { - GST_INFO("Sending pending SetRate(rate=%lf)", rate); + GST_INFO_OBJECT(pipeline_, "Sending pending SetRate(rate=%lf)", rate); SetRate(rate); } } @@ -2883,7 +2932,7 @@ if (GST_MESSAGE_SRC(message) == GST_OBJECT(audio_appsrc_) || GST_MESSAGE_SRC(message) == GST_OBJECT(video_appsrc_)) { int ticket; if (gst_structure_get_int(structure, "ticket", &ticket)) { - GST_INFO("Received '%s' message from %" GST_PTR_FORMAT, kDidReachBufferingTargetMsgName, GST_MESSAGE_SRC(message)); + GST_INFO_OBJECT(pipeline_, "Received '%s' message from %" GST_PTR_FORMAT, kDidReachBufferingTargetMsgName, GST_MESSAGE_SRC(message)); auto type = GST_MESSAGE_SRC(message) == GST_OBJECT(audio_appsrc_) ? MediaType::kAudio : MediaType::kVideo; bool should_update_playing_state = false; ::starboard::ScopedLock lock(mutex_); @@ -2908,12 +2957,12 @@ g_object_set(video_sink, "res-usage", 0x0u, nullptr); } else { - GST_WARNING("'westerossink' has no 'res-usage' property, secondary video may steal decoder"); + GST_WARNING_OBJECT(pipeline_, "'westerossink' has no 'res-usage' property, secondary video may steal decoder"); } g_object_set(pipeline_, "video-sink", video_sink, nullptr); } else { - GST_DEBUG("Failed to create 'westerossink'"); + GST_DEBUG_OBJECT(pipeline_, "Failed to create 'westerossink'"); } gst_object_unref(GST_OBJECT(factory)); } @@ -2989,7 +3038,8 @@ buffering_state_ |= static_cast<int>(MediaType::kAudio); } - if (video_appsrc_) { + if (video_appsrc_ && video_codec_ != kSbMediaVideoCodecNone) { + target += 10 * 16 * GST_MSECOND; if (add_probe(video_appsrc_, target, ticket, buffering_probe_callback) != 0u) buffering_state_ |= static_cast<int>(MediaType::kVideo); } @@ -3035,6 +3085,33 @@ g_source_unref(src); } +void PlayerImpl::DidEnd() { + if (state_ < State::kPresenting) { + DispatchOnWorkerThread( + new PlayerStatusTask( + player_status_func_, player_, ticket_, + context_, kSbPlayerStatePresenting)); + state_ = State::kPresenting; + } + + if (state_ == State::kPresenting) { + DispatchOnWorkerThread( + new PlayerStatusTask( + player_status_func_, player_, ticket_, + context_, kSbPlayerStateEndOfStream)); + state_ = State::kEnded; + } +} + +void PlayerImpl::AudioConfigurationChanged() { + GST_WARNING_OBJECT(pipeline_, "Emitting an error on audio configuration change."); + DispatchOnWorkerThread( + new PlayerErrorTask( + player_error_func_, player_, context_, + kSbPlayerErrorCapabilityChanged, "Audio device capability changed")); + +} + } // namespace void ForceStop() { @@ -3042,6 +3119,11 @@ GetPlayerRegistry()->ForceStop(); } +void AudioConfigurationChanged() { + using third_party::starboard::rdk::shared::player::GetPlayerRegistry; + GetPlayerRegistry()->AudioConfigurationChanged(); +} + } // namespace player } // namespace shared } // namespace rdk @@ -3055,7 +3137,11 @@ SbMediaVideoCodec video_codec, SbMediaAudioCodec audio_codec, SbDrmSystem drm_system, - const SbMediaAudioSampleInfo& audio_sample_info, +#if SB_API_VERSION >= 15 + const SbMediaAudioStreamInfo& audio_info, +#else // SB_API_VERSION >= 15 + const SbMediaAudioSampleInfo& audio_info, +#endif const char* max_video_capabilities, SbPlayerDeallocateSampleFunc sample_deallocate_func, SbPlayerDecoderStatusFunc decoder_status_func, @@ -3063,21 +3149,24 @@ SbPlayerErrorFunc player_error_func, void* context, SbPlayerOutputMode output_mode, - SbDecodeTargetGraphicsContextProvider* provider) - : player_(new PlayerImpl(this, - window, - video_codec, - audio_codec, - drm_system, - audio_sample_info, - max_video_capabilities, - sample_deallocate_func, - decoder_status_func, - player_status_func, - player_error_func, - context, - output_mode, - provider)) { - if ( !static_cast<PlayerImpl&>(*player_).IsValid() ) - player_.reset(nullptr); + SbDecodeTargetGraphicsContextProvider* provider) { + if ( third_party::starboard::rdk::shared::player::GetPlayerRegistry()->CanCreate(max_video_capabilities) ) { + player_.reset( + new PlayerImpl(this, + window, + video_codec, + audio_codec, + drm_system, + audio_info, + max_video_capabilities, + sample_deallocate_func, + decoder_status_func, + player_status_func, + player_error_func, + context, + output_mode, + provider)); + if ( !static_cast<PlayerImpl&>(*player_).IsValid() ) + player_.reset(nullptr); + } }
diff --git a/src/third_party/starboard/rdk/shared/player/player_internal.h b/src/third_party/starboard/rdk/shared/player/player_internal.h index c91ed9c..845031f 100644 --- a/src/third_party/starboard/rdk/shared/player/player_internal.h +++ b/src/third_party/starboard/rdk/shared/player/player_internal.h
@@ -37,10 +37,17 @@ virtual void SetVolume(double volume) = 0; virtual void Seek(SbTime seek_to_timestamp, int ticket) = 0; virtual bool SetRate(double rate) = 0; +#if SB_API_VERSION >= 15 + virtual void GetInfo(SbPlayerInfo* info) = 0; +#else // SB_API_VERSION >= 15 virtual void GetInfo(SbPlayerInfo2* info) = 0; +#endif virtual void SetBounds(int zindex, int x, int y, int w, int h) = 0; }; +void ForceStop(); +void AudioConfigurationChanged(); + } // namespace player } // namespace shared } // namespace rdk @@ -52,7 +59,11 @@ SbMediaVideoCodec video_codec, SbMediaAudioCodec audio_codec, SbDrmSystem drm_system, - const SbMediaAudioSampleInfo& audio_sample_info, +#if SB_API_VERSION >= 15 + const SbMediaAudioStreamInfo& audio_info, +#else // SB_API_VERSION >= 15 + const SbMediaAudioSampleInfo& audio_info, +#endif const char* max_video_capabilities, SbPlayerDeallocateSampleFunc sample_deallocate_func, SbPlayerDecoderStatusFunc decoder_status_func, @@ -67,6 +78,7 @@ using third_party::starboard::rdk::shared::player::Player; return Player::MaxNumberOfSamplesPerWrite(); } + std::unique_ptr<third_party::starboard::rdk::shared::player::Player> player_; };
diff --git a/src/third_party/starboard/rdk/shared/player/player_seek.cc b/src/third_party/starboard/rdk/shared/player/player_seek.cc index 0c1bc19..69ddbce 100644 --- a/src/third_party/starboard/rdk/shared/player/player_seek.cc +++ b/src/third_party/starboard/rdk/shared/player/player_seek.cc
@@ -33,6 +33,12 @@ #include "third_party/starboard/rdk/shared/player/player_internal.h" +#if SB_API_VERSION >= 15 +void SbPlayerSeek(SbPlayer player, SbTime seek_to_timestamp, int ticket) { +#else // SB_API_VERSION >= 15 void SbPlayerSeek2(SbPlayer player, SbTime seek_to_timestamp, int ticket) { +#endif // SB_API_VERSION >= 15 + if (player == kSbPlayerInvalid) + return; player->player_->Seek(seek_to_timestamp, ticket); }
diff --git a/src/third_party/starboard/rdk/shared/player/player_set_bounds.cc b/src/third_party/starboard/rdk/shared/player/player_set_bounds.cc index 84c5627..20b9f7b 100644 --- a/src/third_party/starboard/rdk/shared/player/player_set_bounds.cc +++ b/src/third_party/starboard/rdk/shared/player/player_set_bounds.cc
@@ -39,5 +39,7 @@ int y, int width, int height) { + if (player == kSbPlayerInvalid) + return; player->player_->SetBounds(z_index, x, y, width, height); }
diff --git a/src/third_party/starboard/rdk/shared/player/player_set_playback_rate.cc b/src/third_party/starboard/rdk/shared/player/player_set_playback_rate.cc index e5d2083..3923883 100644 --- a/src/third_party/starboard/rdk/shared/player/player_set_playback_rate.cc +++ b/src/third_party/starboard/rdk/shared/player/player_set_playback_rate.cc
@@ -34,5 +34,7 @@ #include "third_party/starboard/rdk/shared/player/player_internal.h" bool SbPlayerSetPlaybackRate(SbPlayer player, double playback_rate) { + if (player == kSbPlayerInvalid) + return false; return player->player_->SetRate(playback_rate); }
diff --git a/src/third_party/starboard/rdk/shared/player/player_set_volume.cc b/src/third_party/starboard/rdk/shared/player/player_set_volume.cc index 0ad39dc..728fae3 100644 --- a/src/third_party/starboard/rdk/shared/player/player_set_volume.cc +++ b/src/third_party/starboard/rdk/shared/player/player_set_volume.cc
@@ -34,5 +34,7 @@ #include "third_party/starboard/rdk/shared/player/player_internal.h" void SbPlayerSetVolume(SbPlayer player, double volume) { + if (player == kSbPlayerInvalid) + return; player->player_->SetVolume(volume); }
diff --git a/src/third_party/starboard/rdk/shared/player/player_write_end_of_stream.cc b/src/third_party/starboard/rdk/shared/player/player_write_end_of_stream.cc index 23fef23..1b78f87 100644 --- a/src/third_party/starboard/rdk/shared/player/player_write_end_of_stream.cc +++ b/src/third_party/starboard/rdk/shared/player/player_write_end_of_stream.cc
@@ -34,5 +34,7 @@ #include "third_party/starboard/rdk/shared/player/player_internal.h" void SbPlayerWriteEndOfStream(SbPlayer player, SbMediaType stream_type) { + if (player == kSbPlayerInvalid) + return; player->player_->MarkEOS(stream_type); }
diff --git a/src/third_party/starboard/rdk/shared/player/player_write_sample.cc b/src/third_party/starboard/rdk/shared/player/player_write_sample.cc index 335b999..8336b8e 100644 --- a/src/third_party/starboard/rdk/shared/player/player_write_sample.cc +++ b/src/third_party/starboard/rdk/shared/player/player_write_sample.cc
@@ -33,10 +33,17 @@ #include "third_party/starboard/rdk/shared/player/player_internal.h" -void SbPlayerWriteSample2(SbPlayer player, +#if SB_API_VERSION >= 15 +SB_EXPORT void SbPlayerWriteSamples( +#else // SB_API_VERSION >= 15 +SB_EXPORT void SbPlayerWriteSample2( +#endif // SB_API_VERSION >= 15 + SbPlayer player, SbMediaType sample_type, const SbPlayerSampleInfo* sample_infos, int number_of_sample_infos) { + if (player == kSbPlayerInvalid) + return; player->player_->WriteSample(sample_type, sample_infos, number_of_sample_infos); }
diff --git a/src/third_party/starboard/rdk/shared/rdkservices.cc b/src/third_party/starboard/rdk/shared/rdkservices.cc index d29525e..6355fe5 100644 --- a/src/third_party/starboard/rdk/shared/rdkservices.cc +++ b/src/third_party/starboard/rdk/shared/rdkservices.cc
@@ -30,22 +30,29 @@ #include <interfaces/json/JsonData_HDRProperties.h> #include <interfaces/json/JsonData_PlayerProperties.h> #include <interfaces/json/JsonData_DeviceIdentification.h> +#include <interfaces/json/JsonData_DeviceInfo.h> #ifdef HAS_SECURITY_AGENT #include <securityagent/securityagent.h> #endif #include "starboard/atomic.h" +#include "starboard/audio_sink.h" #include "starboard/event.h" +#include "starboard/media.h" #include "starboard/once.h" +#include "starboard/common/atomic.h" #include "starboard/common/condition_variable.h" #include "starboard/common/mutex.h" +#include "starboard/common/media.h" #include "starboard/accessibility.h" #include "starboard/common/file.h" +#include "starboard/shared/starboard/media/mime_supportability_cache.h" #include "third_party/starboard/rdk/shared/accessibility_data.h" #include "third_party/starboard/rdk/shared/log_override.h" #include "third_party/starboard/rdk/shared/application_rdk.h" +#include "third_party/starboard/rdk/shared/player/player_internal.h" MODULE_NAME_DECLARATION(BUILD_REFERENCE); @@ -66,6 +73,9 @@ const char kTTSCallsign[] = "org.rdk.TextToSpeech.1"; const char kAuthServiceCallsign[] = "org.rdk.AuthService.1"; +const char kDeviceInfoCallsign[] = "DeviceInfo.1"; +const char kBluetoothCallsign[] = "org.rdk.Bluetooth.1"; + const char kAuthServiceExperienceFile[] = "/opt/www/authService/experience.dat"; const uint32_t kPriviligedRequestErrorCode = -32604U; @@ -192,6 +202,20 @@ } }; +struct VariableTimeout { + const uint32_t min_ms; // milliseconds + const uint64_t deadline; // ticks + VariableTimeout(uint32_t min, uint32_t max) + : min_ms(min), deadline(Core::Time::Now().Ticks() + max * Core::Time::TicksPerMillisecond) { + } + uint32_t value() const { + auto now = Core::Time::Now().Ticks(); + return (now < deadline) + ? std::max(static_cast<uint32_t>((deadline - now) / Core::Time::TicksPerMillisecond), min_ms) + : min_ms; + } +}; + struct DeviceIdImpl { DeviceIdImpl() { JsonData::DeviceIdentification::DeviceidentificationData data; @@ -808,6 +832,7 @@ private: void Refresh(); void OnUpdated(const Core::JSON::String&); + void ForceNeedsRefresh() { needs_refresh_.store(true); } ServiceLink display_info_ { kDisplayInfoCallsign }; ResolutionInfo resolution_info_ { }; @@ -817,16 +842,19 @@ ::starboard::atomic_bool did_subscribe_ { false }; }; +SB_ONCE_INITIALIZE_FUNCTION(DisplayInfoImpl, GetDisplayInfo); + void DisplayInfoImpl::Refresh() { if (!needs_refresh_.load()) return; + VariableTimeout timeout(kDefaultTimeoutMs, 1000); uint32_t rc; if (!did_subscribe_.load()) { bool old_val = did_subscribe_.exchange(true); if (old_val == false) { - rc = display_info_.Subscribe<Core::JSON::String>(kDefaultTimeoutMs, "updated", &DisplayInfoImpl::OnUpdated, this); + rc = display_info_.Subscribe<Core::JSON::String>(timeout.value(), "updated", &DisplayInfoImpl::OnUpdated, this); if (Core::ERROR_UNAVAILABLE == rc || kPriviligedRequestErrorCode == rc) { needs_refresh_.store(false); SB_LOG(ERROR) << "Failed to subscribe to '" << kDisplayInfoCallsign @@ -848,7 +876,7 @@ bool needs_refresh = false; Core::JSON::String resolution; - rc = ServiceLink(kPlayerInfoCallsign).Get(kDefaultTimeoutMs, "resolution", resolution); + rc = ServiceLink(kPlayerInfoCallsign).Get(timeout.value(), "resolution", resolution); if (Core::ERROR_NONE == rc && resolution.IsSet()) { if (resolution.Value().find("Resolution2160") != std::string::npos) { resolution_info_ = ResolutionInfo { 3840 , 2160 }; @@ -856,20 +884,20 @@ resolution_info_ = ResolutionInfo { 1920 , 1080 }; } } else { - needs_refresh |= (Core::ERROR_ASYNC_FAILED == rc); + needs_refresh |= (Core::ERROR_ASYNC_FAILED == rc || Core::ERROR_TIMEDOUT == rc); resolution_info_ = ResolutionInfo { 1920 , 1080 }; SB_LOG(ERROR) << "Failed to get 'resolution', rc=" << rc << " ( " << Core::ErrorToString(rc) << " )"; } Core::JSON::DecUInt16 widthincentimeters, heightincentimeters; - rc = display_info_.Get(kDefaultTimeoutMs, "widthincentimeters", widthincentimeters); + rc = display_info_.Get(timeout.value(), "widthincentimeters", widthincentimeters); if (Core::ERROR_NONE != rc) { needs_refresh |= (Core::ERROR_ASYNC_FAILED == rc); widthincentimeters.Clear(); SB_LOG(ERROR) << "Failed to get 'DisplayInfo.widthincentimeters', rc=" << rc << " ( " << Core::ErrorToString(rc) << " )"; } - rc = display_info_.Get(kDefaultTimeoutMs, "heightincentimeters", heightincentimeters); + rc = display_info_.Get(timeout.value(), "heightincentimeters", heightincentimeters); if (Core::ERROR_NONE != rc) { needs_refresh |= (Core::ERROR_ASYNC_FAILED == rc); heightincentimeters.Clear(); @@ -888,9 +916,9 @@ HdrTypes types; - uint32_t rc = display_info_.Get(kDefaultTimeoutMs, method, types); + uint32_t rc = display_info_.Get(timeout.value(), method, types); if (Core::ERROR_NONE != rc) { - needs_refresh |= (Core::ERROR_ASYNC_FAILED == rc); + needs_refresh |= (Core::ERROR_ASYNC_FAILED == rc || Core::ERROR_TIMEDOUT == rc); SB_LOG(ERROR) << "Failed to get '" << method << "', rc=" << rc << " ( " << Core::ErrorToString(rc) << " )"; return 0u; } @@ -926,7 +954,15 @@ hdr_caps_ = tv_caps & stb_caps; - needs_refresh_.store(needs_refresh); + needs_refresh_.store(false); + + if (needs_refresh) { + SbEventSchedule([](void* data) { + using ::starboard::shared::starboard::media::MimeSupportabilityCache; + MimeSupportabilityCache::GetInstance()->ClearCachedMimeSupportabilities(); + GetDisplayInfo()->ForceNeedsRefresh(); + }, nullptr, kSbTimeSecond); + } SB_LOG(INFO) << "Display info updated, resolution: " << resolution_info_.Width << 'x' << resolution_info_.Height @@ -940,13 +976,14 @@ if (needs_refresh_.load() == false) { needs_refresh_.store(true); SbEventSchedule([](void* data) { + using ::starboard::shared::starboard::media::MimeSupportabilityCache; + // Clear mime cache until display info is updated + MimeSupportabilityCache::GetInstance()->ClearCachedMimeSupportabilities(); Application::Get()->DisplayInfoChanged(); }, nullptr, 0); } } -SB_ONCE_INITIALIZE_FUNCTION(DisplayInfoImpl, GetDisplayInfo); - struct NetworkInfoImpl { private: ServiceLink network_link_ { kNetworkCallsign }; @@ -1058,12 +1095,10 @@ if (is_connected_.load() != has_connected_interface) { is_connected_.store(has_connected_interface); -#if SB_API_VERSION >= 13 if (has_connected_interface) Application::Get()->InjectOsNetworkConnectedEvent(); else Application::Get()->InjectOsNetworkDisconnectedEvent(); -#endif } } @@ -1112,6 +1147,291 @@ SB_ONCE_INITIALIZE_FUNCTION(NetworkInfoImpl, GetNetworkInfo); +struct DeviceInfoImpl { + + bool GetAudioConfiguration(int index, SbMediaAudioConfiguration* out_audio_configuration); + + void Teardown() { + if (did_subscribe_.load()) { + bluetooth_.Unsubscribe(kDefaultTimeoutMs, "onStatusChanged"); + did_subscribe_.store(false); + } + device_info_.Teardown(); + bluetooth_.Teardown(); + needs_refresh_.store(true); + } + +private: + struct DeviceDetailsData : public Core::JSON::Container { + DeviceDetailsData() + : Core::JSON::Container() { + Init(); + } + DeviceDetailsData(const DeviceDetailsData& other) + : Core::JSON::Container() + , Name(other.Name) + , Devicetype(other.Devicetype) { + Init(); + } + DeviceDetailsData& operator=(const DeviceDetailsData& rhs) { + Name = rhs.Name; + Devicetype = rhs.Devicetype; + return *this; + } + Core::JSON::String Name; + Core::JSON::String Devicetype; + private: + void Init() { + Add(_T("name"), &Name); + Add(_T("deviceType"), &Devicetype); + } + }; + + struct ConnectedDevicesData : public Core::JSON::Container { + ConnectedDevicesData() + : Core::JSON::Container() { + Add(_T("connectedDevices"), &Connecteddevices); + } + ConnectedDevicesData(const ConnectedDevicesData&) = delete; + ConnectedDevicesData& operator=(const ConnectedDevicesData&) = delete; + Core::JSON::ArrayType<DeviceDetailsData> Connecteddevices; + }; + + struct StatusChangedData : public Core::JSON::Container { + StatusChangedData() + : Core::JSON::Container() { + Init(); + } + StatusChangedData(const StatusChangedData& other) + : Core::JSON::Container() + , Name(other.Name) + , Newstatus(other.Newstatus) + , Devicetype(other.Devicetype) + , Connected(other.Connected) { + Init(); + } + StatusChangedData& operator=(const StatusChangedData& rhs) { + Name = rhs.Name; + Devicetype = rhs.Devicetype; + Newstatus = rhs.Newstatus; + Connected = rhs.Connected; + return *this; + } + Core::JSON::String Name; + Core::JSON::String Newstatus; + Core::JSON::String Devicetype; + Core::JSON::Boolean Connected; + private: + void Init() { + Add(_T("name"), &Name); + Add(_T("newStatus"), &Newstatus); + Add(_T("deviceType"), &Devicetype); + Add(_T("connected"), &Connected); + } + }; + + void OnBluetoothStatusChanged(const StatusChangedData&); + void Refresh(); + void ForceNeedsRefresh() { needs_refresh_.store(true); } + void InitAudioConfigurationForAudioPort(const std::string& port_name, SbMediaAudioConfiguration* out); + + static bool IsAudioOutputDeviceType(const std::string& type) { + return (strcasestr(type.c_str(), "audio") || + strcasestr(type.c_str(), "headset") || + strcasestr(type.c_str(), "headphones") || + strcasestr(type.c_str(), "loudspeaker") || + strcasestr(type.c_str(), "handsfree")); + }; + + ServiceLink device_info_ { kDeviceInfoCallsign }; + ServiceLink bluetooth_ { kBluetoothCallsign }; + + ::starboard::atomic_bool did_subscribe_ { false }; + ::starboard::atomic_bool needs_refresh_ { true }; + ::starboard::atomic_bool has_bluetooth_audio_connected_ { false }; + ::starboard::Mutex mutex_; + + std::vector<SbMediaAudioConfiguration> audio_configurations_; + + static constexpr SbMediaAudioConnector kAudioConnectorUnknown = static_cast<SbMediaAudioConnector>(0); +}; + +SB_ONCE_INITIALIZE_FUNCTION(DeviceInfoImpl, GetDeviceInfo); + +void DeviceInfoImpl::InitAudioConfigurationForAudioPort(const std::string& port_name, SbMediaAudioConfiguration* audio_configuration) +{ + if (!audio_configuration) + return; + + const auto& connectorType = [](const std::string& name) { + if (strncasecmp(name.c_str(), "hdmi", 4) == 0) + return kSbMediaAudioConnectorHdmi; + else if (strncasecmp(name.c_str(), "spdif", 5) == 0) + return kSbMediaAudioConnectorSpdif; + else if (strncasecmp(name.c_str(), "bluetooth", 9) == 0) + return kSbMediaAudioConnectorBluetooth; +#if SB_API_VERSION >= 15 + else if (strncasecmp(name.c_str(), "speaker", 7) == 0) + return kSbMediaAudioConnectorBuiltIn; +#endif + return kAudioConnectorUnknown; + }; + + memset(audio_configuration, 0, sizeof(SbMediaAudioConfiguration)); + + audio_configuration->connector = connectorType(port_name); + audio_configuration->coding_type = kSbMediaAudioCodingTypePcm; + audio_configuration->number_of_channels = SbAudioSinkGetMaxChannels(); + return; +} + +void DeviceInfoImpl::OnBluetoothStatusChanged(const StatusChangedData& data) { + const char kConnectionChange[] = "CONNECTION_CHANGE"; + + SB_LOG(INFO) << "Bluetooth status changed, new status: " << data.Newstatus.Value(); + + if (data.Newstatus.Value().compare(0, sizeof(kConnectionChange), kConnectionChange) != 0) + return; + + if (!IsAudioOutputDeviceType(data.Devicetype.Value())) + return; + + SB_LOG(INFO) << "Audio device change." + << " name: '" << data.Name.Value() << "'," + << " type: '" << data.Devicetype.Value() << "'," + << " connected: " << (data.Connected.Value() ? "yes" : "no"); + + const auto& hasBluetoothConnector = [&]() -> bool { + ::starboard::ScopedLock lock(mutex_); + return std::find_if(audio_configurations_.begin(), audio_configurations_.end(), [](const SbMediaAudioConfiguration& cfg) { + return cfg.connector == kSbMediaAudioConnectorBluetooth; + }) != audio_configurations_.end(); + }; + + has_bluetooth_audio_connected_.store(data.Connected.Value()); + + ForceNeedsRefresh(); + + // Interrupt player only if new wireless device got connected + if (data.Connected.Value() && !hasBluetoothConnector()) { + SbEventSchedule([](void*) { + player::AudioConfigurationChanged(); + }, nullptr, 0); + } +} + +void DeviceInfoImpl::Refresh() { + if ( !needs_refresh_.load() || !needs_refresh_.exchange( false ) ) + return; + + std::vector<SbMediaAudioConfiguration> audio_configs; + + uint32_t rc; + bool needs_refresh = false; + VariableTimeout timeout { kDefaultTimeoutMs, 1000 }; + + if (did_subscribe_.load() == false && did_subscribe_.exchange(true) == false) { + rc = bluetooth_.Subscribe<StatusChangedData>(timeout.value(), "onStatusChanged", &DeviceInfoImpl::OnBluetoothStatusChanged, this); + if (Core::ERROR_NONE != rc && Core::ERROR_DUPLICATE_KEY != rc) { + SB_LOG(ERROR) << "Failed to subscribe to '" << kBluetoothCallsign + << ".onStatusChanged' event, rc=" << rc + << " ( " << Core::ErrorToString(rc) << " )"; + } + } + + using namespace WPEFramework::JsonData::DeviceInfo; + SupportedaudioportsData audio_ports; + rc = device_info_.Get(timeout.value(), "supportedaudioports", audio_ports); + if (Core::ERROR_NONE != rc) { + SB_LOG(ERROR) << "'" << kDeviceInfoCallsign << ".supportedaudioports' failed, rc = " << rc + << " ( " << Core::ErrorToString(rc) << " )"; + needs_refresh |= (Core::ERROR_ASYNC_FAILED == rc || Core::ERROR_TIMEDOUT == rc); + } else if (audio_ports.SupportedAudioPorts.Length() == 0) { + SB_LOG(INFO) << "No supported audio ports."; + } else { + auto index(audio_ports.SupportedAudioPorts.Elements()); + while (index.Next()) { + const auto& port_name = index.Current().Value(); + SB_LOG(INFO) << "Supported audio port name: " << port_name; + SbMediaAudioConfiguration configuration; + InitAudioConfigurationForAudioPort(port_name, &configuration); + if (configuration.connector != kAudioConnectorUnknown) + audio_configs.push_back(std::move(configuration)); + } + } + + if (has_bluetooth_audio_connected_.load()) { + SbMediaAudioConfiguration configuration; + InitAudioConfigurationForAudioPort("bluetooth", &configuration); + audio_configs.push_back(std::move(configuration)); + } else { + ConnectedDevicesData connected_devices; + rc = bluetooth_.Get(timeout.value(), "getConnectedDevices", connected_devices); + if (Core::ERROR_NONE != rc) { + SB_LOG(ERROR) << "'" << kBluetoothCallsign << ".getConnectedDevices' failed, rc = " << rc + << " ( " << Core::ErrorToString(rc) << " )"; + needs_refresh |= (Core::ERROR_ASYNC_FAILED == rc || Core::ERROR_TIMEDOUT == rc); + } else if (connected_devices.Connecteddevices.Length() == 0) { + SB_LOG(INFO) << "No bluetooth connected devices."; + } else { + auto index(connected_devices.Connecteddevices.Elements()); + while (index.Next()) { + const auto& device_details = index.Current(); + SB_LOG(INFO) << "Bluetooth device name: " << device_details.Name.Value() << ", type: " << device_details.Devicetype.Value(); + if (IsAudioOutputDeviceType(device_details.Devicetype.Value())) { + SbMediaAudioConfiguration configuration; + InitAudioConfigurationForAudioPort("bluetooth", &configuration); + audio_configs.push_back(std::move(configuration)); + break; + } + } + } + } + + if (audio_configs.empty()) { + SbMediaAudioConfiguration configuration; + InitAudioConfigurationForAudioPort("", &configuration); + audio_configs.push_back(std::move(configuration)); + } + + if (needs_refresh) { + SbEventSchedule([](void* data) { + GetDeviceInfo()->ForceNeedsRefresh(); + }, nullptr, kSbTimeSecond); + } + + SB_LOG(INFO) << "Updated audio configuration:"; + for (const auto& config : audio_configs) { + SB_LOG(INFO) << " connector: " << (uint32_t) config.connector << " (" << ::starboard::GetMediaAudioConnectorName(config.connector) << ")"; + } + + ::starboard::ScopedLock lock(mutex_); + std::swap(audio_configurations_, audio_configs); +} + +bool DeviceInfoImpl::GetAudioConfiguration(int output_index, SbMediaAudioConfiguration* out_configuration) { + SB_DCHECK(output_index >= 0); + SB_DCHECK(out_configuration); + + if (!out_configuration || output_index < 0) + return false; + + Refresh(); + + ::starboard::ScopedLock lock(mutex_); + size_t index = output_index; + if (index < audio_configurations_.size()) { + *out_configuration = audio_configurations_[index]; + return true; + } + else if (index == 0) { + InitAudioConfigurationForAudioPort("", out_configuration); + return true; + } + + return false; +} + } // namespace ResolutionInfo DisplayInfo::GetResolution() { @@ -1238,10 +1558,15 @@ return GetAuthService()->GetExperience(out); } +bool DeviceInfo::GetAudioConfiguration(int index, SbMediaAudioConfiguration* out_audio_configuration) { + return GetDeviceInfo()->GetAudioConfiguration(index, out_audio_configuration); +} + void TeardownJSONRPCLink() { GetDisplayInfo()->Teardown(); GetTextToSpeech()->Teardown(); GetNetworkInfo()->Teardown(); + GetDeviceInfo()->Teardown(); } } // namespace shared
diff --git a/src/third_party/starboard/rdk/shared/rdkservices.h b/src/third_party/starboard/rdk/shared/rdkservices.h index d810bd0..e317ebe 100644 --- a/src/third_party/starboard/rdk/shared/rdkservices.h +++ b/src/third_party/starboard/rdk/shared/rdkservices.h
@@ -25,6 +25,7 @@ struct SbAccessibilityCaptionSettings; struct SbAccessibilityDisplaySettings; +struct SbMediaAudioConfiguration; namespace third_party { namespace starboard { @@ -33,10 +34,10 @@ struct ResolutionInfo { ResolutionInfo() {} - ResolutionInfo(uint32_t w, uint32_t h) + ResolutionInfo(int32_t w, int32_t h) : Width(w), Height(h) {} - uint32_t Width { 1920 }; - uint32_t Height { 1080 }; + int32_t Width { 1920 }; + int32_t Height { 1080 }; }; class DisplayInfo { @@ -111,6 +112,10 @@ static bool GetExperience(std::string &out); }; +class DeviceInfo { +public: + static bool GetAudioConfiguration(int index, SbMediaAudioConfiguration* out_audio_configuration); +}; void TeardownJSONRPCLink();
diff --git a/src/third_party/starboard/rdk/shared/speech/speech_synthesis_cancel.cc b/src/third_party/starboard/rdk/shared/speech/speech_synthesis_cancel.cc index 02ac70c..e757880 100644 --- a/src/third_party/starboard/rdk/shared/speech/speech_synthesis_cancel.cc +++ b/src/third_party/starboard/rdk/shared/speech/speech_synthesis_cancel.cc
@@ -31,10 +31,6 @@ #include "starboard/speech_synthesis.h" #include "third_party/starboard/rdk/shared/rdkservices.h" -#if SB_API_VERSION >= 12 || SB_HAS(SPEECH_SYNTHESIS) - void SbSpeechSynthesisCancel() { third_party::starboard::rdk::shared::TextToSpeech::Cancel(); } - -#endif
diff --git a/src/third_party/starboard/rdk/shared/speech/speech_synthesis_is_supported.cc b/src/third_party/starboard/rdk/shared/speech/speech_synthesis_is_supported.cc index d9e57c4..47f5c27 100644 --- a/src/third_party/starboard/rdk/shared/speech/speech_synthesis_is_supported.cc +++ b/src/third_party/starboard/rdk/shared/speech/speech_synthesis_is_supported.cc
@@ -30,10 +30,6 @@ #include "starboard/speech_synthesis.h" -#if SB_API_VERSION >= 12 - bool SbSpeechSynthesisIsSupported() { return true; } - -#endif
diff --git a/src/third_party/starboard/rdk/shared/speech/speech_synthesis_speak.cc b/src/third_party/starboard/rdk/shared/speech/speech_synthesis_speak.cc index 4772912..d231ef3 100644 --- a/src/third_party/starboard/rdk/shared/speech/speech_synthesis_speak.cc +++ b/src/third_party/starboard/rdk/shared/speech/speech_synthesis_speak.cc
@@ -31,12 +31,8 @@ #include "starboard/speech_synthesis.h" #include "third_party/starboard/rdk/shared/rdkservices.h" -#if SB_API_VERSION >= 12 || SB_HAS(SPEECH_SYNTHESIS) - void SbSpeechSynthesisSpeak(const char* text) { if (!text) return; third_party::starboard::rdk::shared::TextToSpeech::Speak(text); } - -#endif
diff --git a/src/third_party/starboard/rdk/shared/system/system_egl.cc b/src/third_party/starboard/rdk/shared/system/system_egl.cc index 5149cd2..8f2ca67 100644 --- a/src/third_party/starboard/rdk/shared/system/system_egl.cc +++ b/src/third_party/starboard/rdk/shared/system/system_egl.cc
@@ -118,7 +118,7 @@ #ifdef EGL_PLATFORM_WAYLAND_EXT if (gEglCreatePlatformWindowSurfaceEXT) { - result = gEglCreatePlatformWindowSurfaceEXT(dpy, config, (EGLNativeWindowType)win, + result = gEglCreatePlatformWindowSurfaceEXT(dpy, config, (void*)win, attrib_list); if (result == EGL_NO_SURFACE) SB_LOG(WARNING) << "eglCreatePlatformWindowSurfaceEXT failed, err: " << eglGetError();
diff --git a/src/third_party/starboard/rdk/shared/system/system_get_device_type.cc b/src/third_party/starboard/rdk/shared/system/system_get_device_type.cc index a7bf7eb..b96b200 100644 --- a/src/third_party/starboard/rdk/shared/system/system_get_device_type.cc +++ b/src/third_party/starboard/rdk/shared/system/system_get_device_type.cc
@@ -14,6 +14,8 @@ #include "starboard/system.h" #include "starboard/string.h" +#if SB_API_VERSION < 15 + #include <core/Enumerate.h> #include "third_party/starboard/rdk/shared/rdkservices.h" @@ -59,3 +61,5 @@ SB_LOG(INFO) << "DeviceType: 'SetTopBox'"; return kSbSystemDeviceTypeSetTopBox; } + +#endif
diff --git a/src/third_party/starboard/rdk/shared/system/system_get_extensions.cc b/src/third_party/starboard/rdk/shared/system/system_get_extensions.cc index 8dbffdd..8deea82 100644 --- a/src/third_party/starboard/rdk/shared/system/system_get_extensions.cc +++ b/src/third_party/starboard/rdk/shared/system/system_get_extensions.cc
@@ -32,11 +32,12 @@ #include <cstring> -#include "cobalt/extension/platform_service.h" -#include "cobalt/extension/configuration.h" -#include "cobalt/extension/crash_handler.h" + #include "starboard/common/string.h" #include "starboard/common/log.h" +#include "starboard/extension/configuration.h" +#include "starboard/extension/crash_handler.h" +#include "starboard/extension/platform_service.h" #include "third_party/starboard/rdk/shared/configuration.h" #include "third_party/starboard/rdk/shared/platform_service.h" #if SB_IS(EVERGREEN_COMPATIBLE)
diff --git a/src/third_party/starboard/rdk/shared/system/system_get_path.cc b/src/third_party/starboard/rdk/shared/system/system_get_path.cc index be5b04a..ec57651 100644 --- a/src/third_party/starboard/rdk/shared/system/system_get_path.cc +++ b/src/third_party/starboard/rdk/shared/system/system_get_path.cc
@@ -210,26 +210,27 @@ return false; } - char path[kSbFileMaxPath]; + const int kPathSize = kSbFileMaxPath; + char path[kPathSize]; path[0] = '\0'; switch (path_id) { case kSbSystemPathContentDirectory: - if (!GetContentDirectory(path, kSbFileMaxPath)){ + if (!GetContentDirectory(path, kPathSize)){ return false; } #if SB_IS(EVERGREEN_COMPATIBLE) - if (!GetEvergreenContentPathOverride(path, kSbFileMaxPath)) { + if (!GetEvergreenContentPathOverride(path, kPathSize)) { return false; } #endif break; case kSbSystemPathCacheDirectory: - if (!GetCacheDirectory(path, kSbFileMaxPath)) { + if (!GetCacheDirectory(path, kPathSize)) { return false; } - if (starboard::strlcat<char>(path, "/cobalt", kSbFileMaxPath) >= kSbFileMaxPath) { + if (starboard::strlcat<char>(path, "/cobalt", kPathSize) >= kPathSize) { return false; } if (!SbDirectoryCreate(path)) { @@ -238,38 +239,32 @@ break; case kSbSystemPathDebugOutputDirectory: - if (!SbSystemGetPath(kSbSystemPathTempDirectory, path, kSbFileMaxPath)) { + if (!SbSystemGetPath(kSbSystemPathTempDirectory, path, kPathSize)) { return false; } - if (starboard::strlcat<char>(path, "/log", kSbFileMaxPath) >= kSbFileMaxPath) { + if (starboard::strlcat<char>(path, "/log", kPathSize) >= kPathSize) { return false; } SbDirectoryCreate(path); break; case kSbSystemPathTempDirectory: - if (!GetTemporaryDirectory(path, kSbFileMaxPath)) { + if (!GetTemporaryDirectory(path, kPathSize)) { return false; } SbDirectoryCreate(path); break; -#if SB_API_VERSION < 14 - case kSbSystemPathTestOutputDirectory: - return SbSystemGetPath(kSbSystemPathDebugOutputDirectory, out_path, - path_size); -#endif // #if SB_API_VERSION < 14 - case kSbSystemPathExecutableFile: return GetExecutablePath(out_path, path_size); case kSbSystemPathFontConfigurationDirectory: case kSbSystemPathFontDirectory: #if SB_IS(EVERGREEN_COMPATIBLE) - if (!GetContentDirectory(path, kSbFileMaxPath)) { + if (!GetContentDirectory(path, kPathSize)) { return false; } - if (starboard::strlcat(path, "/fonts", kSbFileMaxPath) >= kSbFileMaxPath) { + if (starboard::strlcat(path, "/fonts", kPathSize) >= kPathSize) { return false; } break; @@ -277,13 +272,11 @@ return false; #endif -#if SB_API_VERSION >= 12 case kSbSystemPathStorageDirectory: - if (!GetStorageDirectory(path, kSbFileMaxPath)) { + if (!GetStorageDirectory(path, kPathSize)) { return false; } break; -#endif default: SB_NOTIMPLEMENTED() << "SbSystemGetPath not implemented for " << path_id;
diff --git a/src/third_party/starboard/rdk/shared/system/system_get_property.cc b/src/third_party/starboard/rdk/shared/system/system_get_property.cc index 2aec496..6207ec2 100644 --- a/src/third_party/starboard/rdk/shared/system/system_get_property.cc +++ b/src/third_party/starboard/rdk/shared/system/system_get_property.cc
@@ -39,7 +39,6 @@ #include "starboard/common/log.h" #include "starboard/common/string.h" #include "starboard/common/file.h" -#include "starboard/character.h" #include "starboard/file.h" #include "third_party/starboard/rdk/shared/rdkservices.h" @@ -52,7 +51,7 @@ const char kPlatformName[] = "Linux"; bool CopyStringAndTestIfSuccess(char* out_value, - int value_length, + size_t value_length, const char* from_value) { if (strlen(from_value) + 1 > value_length) return false; @@ -60,7 +59,7 @@ return true; } -bool TryReadFromPropertiesFile(const char* prefix, size_t prefix_len, char* out_value, int value_length) { +bool TryReadFromPropertiesFile(const char* prefix, size_t prefix_len, char* out_value, size_t value_length) { FILE* properties = fopen("/etc/device.properties", "r"); if (!properties) { return false; @@ -256,6 +255,19 @@ return false; } +#if SB_API_VERSION >= 15 +bool GetDeviceType(char* out_value, int value_length) { + std::string prop; + if (AuthService::GetExperience(prop) && prop == "Flex") { + prop = "OTT"; + } + else if (!SystemProperties::GetDeviceType(prop)) { + prop = "STB"; + } + return CopyStringAndTestIfSuccess(out_value, value_length, prop.c_str()); +} +#endif + } // namespace bool SbSystemGetProperty(SbSystemPropertyId property_id, @@ -295,18 +307,17 @@ case kSbSystemPropertyCertificationScope: return GetCertificationScope(out_value, value_length); -#if SB_API_VERSION < 13 - case kSbSystemPropertyBase64EncodedCertificationSecret: - return false; -#endif -#if SB_API_VERSION >= 14 case kSbSystemPropertyAdvertisingId: return GetAdvertisingId(out_value, value_length); + case kSbSystemPropertyLimitAdTracking: return GetLimitAdTracking(out_value, value_length); -#endif +#if SB_API_VERSION >= 15 + case kSbSystemPropertyDeviceType: + return GetDeviceType(out_value, value_length); +#endif default: SB_DLOG(WARNING) << __FUNCTION__ << ": Unrecognized property: " << property_id;
diff --git a/src/third_party/starboard/rdk/shared/system/system_get_total_cpu_memory.cc b/src/third_party/starboard/rdk/shared/system/system_get_total_cpu_memory.cc new file mode 100644 index 0000000..27e68c4 --- /dev/null +++ b/src/third_party/starboard/rdk/shared/system/system_get_total_cpu_memory.cc
@@ -0,0 +1,69 @@ +// +// Copyright 2020 Comcast Cable Communications Management, LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Copyright 2016 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/system.h" + +#include <unistd.h> + +#include "starboard/common/file.h" +#include "starboard/common/log.h" +#include "starboard/common/string.h" + +int64_t SbSystemGetTotalCPUMemory() { + + int64_t limit_in_bytes = INT64_MAX; + + starboard::ScopedFile status_file( + "/sys/fs/cgroup/memory/memory.limit_in_bytes", + kSbFileOpenOnly | kSbFileRead); + + if (status_file.IsValid()) { + const int kBufferSize = 512; + char buffer[kBufferSize]; + int bytes_read = status_file.ReadAll(buffer, kBufferSize); + if (bytes_read == kBufferSize) { + bytes_read = kBufferSize - 1; + } + buffer[bytes_read] = '\0'; + int64_t val = strtoll(buffer, nullptr, 10); + if (val > 0) + limit_in_bytes = val; + } + + long pages = sysconf(_SC_PHYS_PAGES); // NOLINT[runtime/int] + long page_size = sysconf(_SC_PAGE_SIZE); // NOLINT[runtime/int] + if (pages == -1 || page_size == -1) { + SB_NOTREACHED(); + return 0; + } + + return std::min(limit_in_bytes, static_cast<int64_t>(pages) * page_size); +}
diff --git a/src/third_party/starboard/rdk/shared/system/system_get_connection_type.cc b/src/third_party/starboard/rdk/shared/system/system_get_total_gpu_memory.cc similarity index 66% rename from src/third_party/starboard/rdk/shared/system/system_get_connection_type.cc rename to src/third_party/starboard/rdk/shared/system/system_get_total_gpu_memory.cc index 8db9bf4..21cee44 100644 --- a/src/third_party/starboard/rdk/shared/system/system_get_connection_type.cc +++ b/src/third_party/starboard/rdk/shared/system/system_get_total_gpu_memory.cc
@@ -1,3 +1,4 @@ +// // Copyright 2020 Comcast Cable Communications Management, LLC // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -30,14 +31,27 @@ #include "starboard/system.h" -#include "third_party/starboard/rdk/shared/rdkservices.h" +#include "starboard/common/file.h" +#include "starboard/common/log.h" +#include "starboard/common/string.h" -#if SB_API_VERSION < 14 -SbSystemConnectionType SbSystemGetConnectionType() { - if (third_party::starboard::rdk::shared::NetworkInfo::IsConnectionTypeWireless()) { - return kSbSystemConnectionTypeWireless; - } else { - return kSbSystemConnectionTypeWired; +int64_t SbSystemGetTotalGPUMemory() { + starboard::ScopedFile status_file( + "/sys/fs/cgroup/gpu/gpu.limit_in_bytes", + kSbFileOpenOnly | kSbFileRead); + + if (status_file.IsValid()) { + const int kBufferSize = 512; + char buffer[kBufferSize]; + int bytes_read = status_file.ReadAll(buffer, kBufferSize); + if (bytes_read == kBufferSize) { + bytes_read = kBufferSize - 1; + } + buffer[bytes_read] = '\0'; + int64_t limit_in_bytes = strtoll(buffer, nullptr, 10); + if (limit_in_bytes > 0) + return limit_in_bytes; } + + return 0; } -#endif // #if SB_API_VERSION < 14
diff --git a/src/third_party/starboard/rdk/shared/system/system_get_connection_type.cc b/src/third_party/starboard/rdk/shared/system/system_get_used_gpu_memory.cc similarity index 65% copy from src/third_party/starboard/rdk/shared/system/system_get_connection_type.cc copy to src/third_party/starboard/rdk/shared/system/system_get_used_gpu_memory.cc index 8db9bf4..d7c5b9e 100644 --- a/src/third_party/starboard/rdk/shared/system/system_get_connection_type.cc +++ b/src/third_party/starboard/rdk/shared/system/system_get_used_gpu_memory.cc
@@ -1,3 +1,4 @@ +// // Copyright 2020 Comcast Cable Communications Management, LLC // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -30,14 +31,29 @@ #include "starboard/system.h" -#include "third_party/starboard/rdk/shared/rdkservices.h" +#include "starboard/common/file.h" +#include "starboard/common/log.h" +#include "starboard/common/string.h" -#if SB_API_VERSION < 14 -SbSystemConnectionType SbSystemGetConnectionType() { - if (third_party::starboard::rdk::shared::NetworkInfo::IsConnectionTypeWireless()) { - return kSbSystemConnectionTypeWireless; - } else { - return kSbSystemConnectionTypeWired; +#include <cerrno> + +int64_t SbSystemGetUsedGPUMemory() { + starboard::ScopedFile status_file( + "/sys/fs/cgroup/gpu/gpu.usage_in_bytes", + kSbFileOpenOnly | kSbFileRead); + + if (status_file.IsValid()) { + const int kBufferSize = 512; + char buffer[kBufferSize]; + int bytes_read = status_file.ReadAll(buffer, kBufferSize); + if (bytes_read == kBufferSize) { + bytes_read = kBufferSize - 1; + } + buffer[bytes_read] = '\0'; + int64_t usage_in_bytes = strtoll(buffer, nullptr, 10); + if (usage_in_bytes > 0 && errno != ERANGE) + return usage_in_bytes; } + + return 0; } -#endif // #if SB_API_VERSION < 14
diff --git a/src/third_party/starboard/rdk/shared/system/system_has_capability.cc b/src/third_party/starboard/rdk/shared/system/system_has_capability.cc index 60a9290..c514cb0 100644 --- a/src/third_party/starboard/rdk/shared/system/system_has_capability.cc +++ b/src/third_party/starboard/rdk/shared/system/system_has_capability.cc
@@ -14,17 +14,15 @@ #include "starboard/system.h" #include "starboard/common/log.h" +#include "starboard/file.h" bool SbSystemHasCapability(SbSystemCapabilityId capability_id) { switch (capability_id) { case kSbSystemCapabilityReversedEnterAndBack: return false; case kSbSystemCapabilityCanQueryGPUMemoryStats: - return false; -#if SB_API_VERSION < 13 - case kSbSystemCapabilitySetsInputTimestamp: - return false; -#endif + static bool gpu_stats_exists_cached = SbFileExists("/sys/fs/cgroup/gpu/gpu.usage_in_bytes"); + return gpu_stats_exists_cached; } SB_DLOG(WARNING) << "Unrecognized capability: " << capability_id;
diff --git a/src/third_party/starboard/rdk/shared/system/system_request_conceal.cc b/src/third_party/starboard/rdk/shared/system/system_request_conceal.cc index 32f5437..1cf8c42 100644 --- a/src/third_party/starboard/rdk/shared/system/system_request_conceal.cc +++ b/src/third_party/starboard/rdk/shared/system/system_request_conceal.cc
@@ -32,8 +32,6 @@ #include "third_party/starboard/rdk/shared/libcobalt.h" -#if SB_API_VERSION >= 13 void SbSystemRequestConceal() { SbRdkRequestConceal(); } -#endif // SB_API_VERSION >= 13
diff --git a/src/third_party/starboard/rdk/shared/system/system_sign_with_certification_secret_key.cc b/src/third_party/starboard/rdk/shared/system/system_sign_with_certification_secret_key.cc index aa929d4..8b55044 100644 --- a/src/third_party/starboard/rdk/shared/system/system_sign_with_certification_secret_key.cc +++ b/src/third_party/starboard/rdk/shared/system/system_sign_with_certification_secret_key.cc
@@ -32,6 +32,7 @@ #include <vector> #include <cstring> +#include "starboard/file.h" #include "starboard/system.h" #include "starboard/string.h" #include "starboard/memory.h" @@ -41,8 +42,10 @@ #if defined(HAS_CRYPTOGRAPHY) #include <cryptography/cryptography.h> +#if defined(HAS_RFC_API) #include <rfcapi.h> #endif +#endif namespace { @@ -71,9 +74,6 @@ using CryptographyVault = cryptographyvault; #endif - const char kDefaultKeyName[] = "0381000003810001.key"; - const char kRFCParamName[] = "Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.Cobalt.AuthCertKeyName"; - third_party::starboard::rdk::shared::HangMonitor hang_monitor(__func__); std::string key_name; @@ -82,6 +82,8 @@ key_name = env; SB_LOG(INFO) << "Using ENV set key name: '" << key_name << "'"; } else { +#if defined(HAS_RFC_API) + const char kRFCParamName[] = "Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.Cobalt.AuthCertKeyName"; char *callerId = SbStringDuplicate("Cobalt"); RFC_ParamData_t param; memset(¶m, 0, sizeof (param)); @@ -91,19 +93,36 @@ SB_LOG(INFO) << "Using RFC provided key name: '" << key_name << "'"; } SbMemoryDeallocate(callerId); +#endif } if ( key_name.empty() ) { + const char kDefaultKeyName[] = "0381000003810001.key"; key_name = kDefaultKeyName; SB_LOG(INFO) << "Using default key name: '" << key_name << "'"; } + const char *env_connection_point = std::getenv("COBALT_ICRYPTO_ACCESS_POINT"); + std::string connection_point = env_connection_point ? env_connection_point : EMPTY_STRING; + + if (env_connection_point != nullptr) { + if (SbFileExists(env_connection_point)) + connection_point = env_connection_point; + else + SB_LOG(WARNING) << "ICrypto connection point ('" << env_connection_point << "') does not exist."; + } + + if (connection_point.empty()) + SB_LOG(INFO) << "Using ICrypto directly."; + else + SB_LOG(INFO) << "Using ICrypto connection point: '" << connection_point << "'."; + ScopedRef<ICryptography> icrypto; ScopedRef<IVault> vault; ScopedRef<IPersistent> persistent; ScopedRef<IHash> hash; - icrypto.reset( ICryptography::Instance(EMPTY_STRING) ); + icrypto.reset( ICryptography::Instance(connection_point) ); if ( !icrypto ) { SB_LOG(ERROR) << "Failed to create ICryptography instance"; return false;
diff --git a/src/third_party/starboard/rdk/shared/time_zone_get_name.cc b/src/third_party/starboard/rdk/shared/time_zone_get_name.cc new file mode 100644 index 0000000..25a9a53 --- /dev/null +++ b/src/third_party/starboard/rdk/shared/time_zone_get_name.cc
@@ -0,0 +1,108 @@ +// +// Copyright 2020 Comcast Cable Communications Management, LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2015 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Based on code from ICU which is: +// Copyright 2016-2023 Unicode, Inc. +// and +// Copyright (c) 1995-2016 International Business Machines Corporation and others +// All rights reserved. +// Licensed under UNICODE LICENSE V3 and the ICU License from https://github.com/unicode-org/icu/blob/main/LICENSE + +#include <string.h> +#include <time.h> +#include <unistd.h> + +#include "starboard/common/log.h" +#include "starboard/time_zone.h" + +#define TZDEFAULT "/etc/localtime" +#define TZZONEINFOTAIL "/zoneinfo/" +#define isNonDigit(ch) (ch < '0' || '9' < ch) + +static char gTimeZoneBuffer[PATH_MAX]; +static char* gTimeZoneBufferPtr = NULL; + +static bool isValidOlsonID(const char* id) { + int32_t idx = 0; + + /* Determine if this is something like Iceland (Olson ID) + or AST4ADT (non-Olson ID) */ + while (id[idx] && isNonDigit(id[idx]) && id[idx] != ',') { + idx++; + } + + /* If we went through the whole string, then it might be okay. + The timezone is sometimes set to "CST-7CDT", "CST6CDT5,J129,J131/19:30", + "GRNLNDST3GRNLNDDT" or similar, so we cannot use it. + The rest of the time it could be an Olson ID. George */ + return static_cast<bool>(id[idx] == 0 || strcmp(id, "PST8PDT") == 0 || + strcmp(id, "MST7MDT") == 0 || + strcmp(id, "CST6CDT") == 0 || + strcmp(id, "EST5EDT") == 0); +} + +// Similar to how ICU::putil.cpp gets IANA(Olsen) timezone ID. +const char* SbTimeZoneGetName() { + /* Check TZ variable */ + if (gTimeZoneBufferPtr == NULL) { + const char* tz = getenv("TZ"); + if (tz && isValidOlsonID(tz)) { + strncpy(gTimeZoneBuffer, tz, sizeof(gTimeZoneBuffer)); + gTimeZoneBuffer[sizeof(gTimeZoneBuffer) - 1] = 0; + gTimeZoneBufferPtr = &gTimeZoneBuffer[0]; + } + } + + /* + This is a trick to look at the name of the link to get the Olson ID + because the tzfile contents is underspecified. + This isn't guaranteed to work because it may not be a symlink. + But this is production-tested solution for most versions of Linux. + */ + + if (gTimeZoneBufferPtr == NULL) { + int32_t ret = (int32_t)readlink(TZDEFAULT, gTimeZoneBuffer, + sizeof(gTimeZoneBuffer) - 1); + if (0 < ret) { + int32_t tzZoneInfoTailLen = strlen(TZZONEINFOTAIL); + gTimeZoneBuffer[ret] = 0; + char* tzZoneInfoTailPtr = strstr(gTimeZoneBuffer, TZZONEINFOTAIL); + + if (tzZoneInfoTailPtr != NULL && + isValidOlsonID(tzZoneInfoTailPtr + tzZoneInfoTailLen)) { + return (gTimeZoneBufferPtr = tzZoneInfoTailPtr + tzZoneInfoTailLen); + } + } + SB_NOTREACHED(); + return ""; + } else { + return gTimeZoneBufferPtr; + } +}