This patch enables below patch for 4k support of AV1 and HEVC codecs.
Reference:
https://review.tizen.org/gerrit/#/c/277038/
Change-Id: I9d53ecddedb74cef5065da8ef3eb60b6335641f3
Signed-off-by: Sun-woo Nam <sunny.nam@samsung.com>
#endif // !BUILDFLAG(USE_PROPRIETARY_CODECS)
bool IsHevcProfileSupported(const VideoType& type) {
+#if defined(TIZEN_MULTIMEDIA)
+ return BUILDFLAG(ENABLE_PLATFORM_HEVC);
+#endif
+
if (!IsColorSpaceSupported(type.color_space))
return false;
case VideoCodec::kAV1:
return IsAV1Supported(type);
case VideoCodec::kVP9:
+#if defined(TIZEN_MULTIMEDIA)
+ return true;
+#else
return IsVp9ProfileSupported(type);
+#endif
case VideoCodec::kHEVC:
return IsHevcProfileSupported(type);
case VideoCodec::kMPEG4:
enable_hevc_parser_and_hw_decoder =
proprietary_codecs &&
(use_fuzzing_engine || use_chromeos_protected_media || is_win || is_mac ||
- is_android || is_linux)
+ is_android || is_linux || tizen_product_tv)
}
# Use another declare_args() to allow dependence on
declare_args() {
# If overriding this to false, possibly via its component values,
# `enable_libaom` should likely also be overriddent to false.
- enable_av1_decoder = enable_dav1d_decoder || enable_libgav1_decoder
+ enable_av1_decoder =
+ enable_dav1d_decoder || enable_libgav1_decoder || tizen_product_tv
# Enable HEVC/H265 demuxing. Actual decoding must be provided by the
# platform.
BuildRequires: pkgconfig(cynara-client)
BuildRequires: pkgconfig(drmdecrypt)
BuildRequires: pkgconfig(efl-assist)
+BuildRequires: pkgconfig(hdmicec-api)
BuildRequires: pkgconfig(lwipc)
BuildRequires: pkgconfig(privileged-service)
+BuildRequires: pkgconfig(tv-resource-manager)
+BuildRequires: pkgconfig(tv-resource-information)
BuildRequires: pkgconfig(vd-win-util)
BuildRequires: pkgconfig(WebProduct)
%endif
"video_playback_quality.cc",
"video_playback_quality.h",
]
+ configs += [ "//tizen_src/build:tizen-tv-resource-manager-config" ]
deps = [
"//build:chromeos_buildflags",
"//media",
#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#if BUILDFLAG(IS_TIZEN_TV)
+#include <ri-api.h>
+#include "hdmicec_api.h"
+#include "tizen_src/chromium_impl/build/tizen_version.h"
+#include "tizen_src/chromium_impl/tizen/tizen_tv_platform.h"
+#endif
+
using blink::WebMediaSource;
using blink::WebSourceBuffer;
return false;
}
+#if BUILDFLAG(IS_TIZEN_TV)
+ if (!MediaSource::IsCodecAndMediaTypeSupported(content_type)) {
+ DVLOG(1) << __func__ << "(" << type
+ << ") -> false (invalid addditional type)";
+ return false;
+ }
+#endif
+
// 3. If type contains a media type or media subtype that the MediaSource does
// not support, then return false.
// 4. If type contains at a codec that the MediaSource does not support, then
async_event_queue_->EnqueueEvent(FROM_HERE, *event);
}
+#if BUILDFLAG(IS_TIZEN_TV)
+bool MediaSource::IsAV1SupportedOnTizen() {
+#if TIZEN_VERSION_AT_LEAST(6, 0, 0)
+ return ri_is_supported_video_codec(RI_CODEC_NAME_AV1);
+#else
+ std::string chipset = GetTVChipset();
+ // av1 is supported only on these chipsets
+ return (chipset == "OSCARP" || chipset == "NIKEM" || chipset == "NIKEM2" ||
+ chipset == "NIKEL" || chipset == "KANTSU2");
+#endif
+}
+
+bool MediaSource::IsCodecAndMediaTypeSupported(
+ const ContentType& content_type) {
+ DVLOG(1) << __func__ << "MediaSource Extention Type (W="
+ << content_type.Parameter("width").ToInt()
+ << ", xH=" << content_type.Parameter("height").ToInt()
+ << ", dfps=" << content_type.Parameter("framerate").ToInt()
+ << ", fMbps=" << content_type.Parameter("bitrate").ToInt()
+ << ", dchannels=" << content_type.Parameter("channels").ToInt()
+ << ")";
+ const int k8K_panel_width = 7680;
+ const int k8K_panel_height = 4320;
+ const int UHD_panel_width = 3840;
+ const int UHD_panel_height = 2160;
+ const int FHD_panel_width = 1920;
+ const int FHD_panel_height = 1080;
+ const char dolby_eac3_atmos[] = "JOC";
+ const int res_width = content_type.Parameter("width").ToInt();
+ const int res_height = content_type.Parameter("height").ToInt();
+ // don't support 4K for avc1 and h264
+ if (content_type.Parameter("codecs").FindIgnoringCase("avc1") !=
+ WTF::kNotFound ||
+ content_type.Parameter("codecs").FindIgnoringCase("h264") !=
+ WTF::kNotFound) {
+ if (res_width > FHD_panel_width || res_height > FHD_panel_height)
+ return false;
+ }
+
+ String features = content_type.Parameter("features");
+ if (!features.empty()) {
+ return false;
+ }
+
+ static int panel_width = 0;
+ if (!panel_width) {
+ panel_width = GetTVPanelWidth();
+ if (!panel_width) {
+ panel_width = FHD_panel_width;
+ }
+ }
+
+ // device exception :
+ // some device can decode larger than panel and requests to play it.
+ // we may know this exceptional case by checking AV1 max size.
+ // ex) micro led TV. 4k panel, 8k ability. FMS is 4k.
+ if (ri_is_supported_video_codec(RI_CODEC_NAME_AV1)) {
+ int ri_max_width = 0;
+ int ri_max_height = 0;
+ int ri_max_framerate = 0;
+ if (ri_get_max_resolution(RI_CODEC_NAME_AV1, &ri_max_width, &ri_max_height,
+ &ri_max_framerate) == RI_OK) {
+ if (panel_width * 2 <= ri_max_width) {
+ LOG(INFO) << "Panel size adjust twice!";
+ panel_width *= 2;
+ }
+ } else {
+ LOG(WARNING) << "Failed to get video max information";
+ }
+ }
+ LOG(INFO) << "Panel width is " << panel_width;
+
+ switch (panel_width) {
+ case k8K_panel_width:
+ if (res_width > k8K_panel_width || res_height > k8K_panel_height)
+ return false;
+ break;
+ case UHD_panel_width:
+ if (res_width > UHD_panel_width || res_height > UHD_panel_height)
+ return false;
+ break;
+ default:
+ if (res_width > FHD_panel_width || res_height > FHD_panel_height)
+ return false;
+ break;
+ }
+
+ const int max_framerate = 60;
+ const int stable_framerate = 30;
+ const int max_bitrate = 60;
+ const int stable_bitrate = 30;
+ const int max_audio_channels = 6;
+ const int unit = 1000000;
+
+ int support_max_bitrate = max_bitrate;
+ int support_max_framerate = max_framerate;
+ static int max_VP9_bitrate = 0;
+ static int max_VP9_framerate = 0;
+ const String eotf = content_type.Parameter("eotf");
+ const String crypto_block_format =
+ content_type.Parameter("cryptoblockformat");
+ const bool is_AV1 = content_type.Parameter("codecs").FindIgnoringCase(
+ "av01") != WTF::kNotFound;
+ if (is_AV1 && !IsAV1SupportedOnTizen())
+ return false;
+
+ // 8k should be supported only by AV1
+ if (!is_AV1 && (res_width > UHD_panel_width || res_height > UHD_panel_height))
+ return false;
+
+ if (is_AV1 ||
+ content_type.Parameter("codecs").FindIgnoringCase("vp9") !=
+ WTF::kNotFound ||
+ content_type.Parameter("codecs").FindIgnoringCase("vp09") !=
+ WTF::kNotFound) {
+ auto isHDRSupported = [](const std::string& eotf) -> bool {
+ const static std::set<std::string> hdr_type{"bt709", "smpte2084",
+ "arib-std-b67", "cuva_hdr"};
+ if (!eotf.empty() && hdr_type.find(eotf) == hdr_type.end())
+ return false;
+ if (eotf == "cuva_hdr")
+ return IsCuvaHDRSupported();
+
+ return true;
+ };
+ if (!isHDRSupported(eotf.Ascii()))
+ return false;
+
+ if (!crypto_block_format.empty() && crypto_block_format != "subsample")
+ return false;
+
+ if (!max_VP9_bitrate) {
+ max_VP9_bitrate = GetTVMaxBitrate();
+ if (!max_VP9_bitrate) {
+ max_VP9_bitrate = stable_bitrate;
+ }
+ }
+ support_max_bitrate = max_VP9_bitrate;
+
+ if (!max_VP9_framerate) {
+ max_VP9_framerate = GetTVMaxFramerate();
+ if (!max_VP9_framerate) {
+ max_VP9_framerate = stable_framerate;
+ }
+ }
+ support_max_framerate = max_VP9_framerate;
+ } else {
+ if (!crypto_block_format.empty())
+ return false;
+ if (!eotf.empty())
+ return false;
+ }
+ DVLOG(1) << __func__ << "(SYSTEM INFO: Bitrate fMbps=" << support_max_bitrate
+ << ", dfps=" << support_max_framerate << ")";
+ if (content_type.Parameter("bitrate").ToInt() > support_max_bitrate * unit ||
+ content_type.Parameter("framerate").ToInt() > support_max_framerate)
+ return false;
+
+ if (!content_type.Parameter("channels").empty() &&
+ (content_type.Parameter("channels").ToInt() > max_audio_channels ||
+ content_type.Parameter("channels").ToInt() <= 0))
+ return false;
+
+ return true;
+}
+#endif
+
} // namespace blink
namespace blink {
+#if BUILDFLAG(IS_TIZEN_TV)
+class ContentType;
+#endif
class EventQueue;
class ExceptionState;
class HTMLMediaElement;
MediaSourceAttachmentSupplement::ExclusiveKey pass_key)
LOCKS_EXCLUDED(attachment_link_lock_);
+#if BUILDFLAG(IS_TIZEN_TV)
+ static bool IsAV1SupportedOnTizen();
+ static bool IsCodecAndMediaTypeSupported(const ContentType&);
+#endif
+
// Usage of |*web_media_source_| must be within scope of attachment's
// RunExclusively() callback to prevent potential UAF of underlying demuxer
// resources when MSE is in worker thread. Setting it or resetting it do not
}
}
+tizen_pkg_config("tizen-tv-resource-manager-config") {
+ packages = []
+ if (tizen_product_tv) {
+ packages += [
+ "tv-resource-manager",
+ "tv-resource-information",
+ ]
+ }
+}
+
config("gstreamer") {
if (is_tizen) {
ldflags = [
}
}
+config("hdmicec-api") {
+ if (tizen_product_tv) {
+ ldflags = [ "-lhdmicec-api" ]
+ }
+}
+
+tizen_pkg_config("libhdmicec-api") {
+ packages = []
+ if (tizen_product_tv) {
+ packages = [ "hdmicec-api" ]
+ }
+}
+
config("vconf") {
if (is_tizen) {
ldflags = [ "-lvconf" ]
tizen_autofill = false
tizen_autofill_fw = false
+
+ tizen_resource_manager = false
}
if (is_tizen) {
#include "base/logging.h"
+#if BUILDFLAG(IS_TIZEN_TV)
+#include "tizen_src/chromium_impl/tizen/tizen_tv_platform.h"
+#endif
+
namespace {
#define ENUM_CASE(x) \
bool is_video_hole) {
switch (mime_type) {
case ESPLUSPLAYER_VIDEO_MIME_TYPE_AV1:
+ case ESPLUSPLAYER_VIDEO_MIME_TYPE_HEVC:
+ case ESPLUSPLAYER_VIDEO_MIME_TYPE_VP9:
return {k8KVideoMaxWidth, k8KVideoMaxHeight};
case ESPLUSPLAYER_VIDEO_MIME_TYPE_VP8:
return {kFHDVideoMaxWidth, kFHDVideoMaxHeight};
- case ESPLUSPLAYER_VIDEO_MIME_TYPE_VP9:
- case ESPLUSPLAYER_VIDEO_MIME_TYPE_HEVC:
- return {k8KVideoMaxWidth, k8KVideoMaxHeight};
case ESPLUSPLAYER_VIDEO_MIME_TYPE_H264:
if (is_video_hole)
return {k4KVideoMaxWidth, k4KVideoMaxHeight};
}
}
+gfx::Size GetPanelResolution() {
+#if BUILDFLAG(IS_TIZEN_TV)
+ int panel_width = GetTVPanelWidth();
+ int panel_height = GetTVPanelHeight();
+#else
+ int panel_width = 0;
+ int panel_height = 0;
+#endif
+ if (!panel_width || !panel_height) {
+ panel_width = kFHDVideoMaxWidth;
+ panel_height = kFHDVideoMaxHeight;
+ }
+
+ LOG(INFO) << "Panel resolution: " << panel_width << " x " << panel_height;
+ return {panel_width, panel_height};
+}
+
+gfx::Size GetMaxResolution(esplusplayer_video_mime_type mime_type,
+ bool is_video_hole) {
+ const auto max_codec_resolution =
+ GetMaxCodecResolution(mime_type, is_video_hole);
+ const auto panel_resolution = GetPanelResolution();
+ return {std::min(max_codec_resolution.width(), panel_resolution.width()),
+ std::min(max_codec_resolution.height(), panel_resolution.height())};
+}
+
esplusplayer_display_rotation_type ConvertToESPlusPlayerDisplayRotation(
int rotation) {
switch (rotation) {
gfx::Size GetMaxCodecResolution(esplusplayer_video_mime_type mime_type,
bool is_video_hole);
+gfx::Size GetPanelResolution();
+gfx::Size GetMaxResolution(esplusplayer_video_mime_type mime_type,
+ bool is_video_hole);
esplusplayer_display_rotation_type ConvertToESPlusPlayerDisplayRotation(
int rotation);
video_stream_info.codec_data = NULL;
}
auto max_resolution =
- GetMaxCodecResolution(video_stream_info.mime_type, is_video_hole_);
+ GetMaxResolution(video_stream_info.mime_type, is_video_hole_);
video_stream_info.max_width = max_resolution.width();
video_stream_info.max_height = max_resolution.height();
"system_info.cc",
"system_info.h",
]
- if (is_tizen) {
+
+ if (tizen_product_tv) {
sources += [
+ "tizen_tv_platform.h",
"vconf_handle.cc",
"vconf_handle.h",
]
--- /dev/null
+// Copyright 2022 Samsung Electronics Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TIZEN_TV_SYSTEM_INFO
+#define TIZEN_TV_SYSTEM_INFO
+
+#if BUILDFLAG(IS_TIZEN_TV)
+#include <capi-system-info/system_info.h>
+#include <fstream>
+
+// RM index is not available at public include. It had to be copied from
+// Resource-mgr/resource-info/include_internal/parser/CResourceTableProvider.h
+enum class ResourceTableIndex {
+ DTV_UNKNOWN = -1,
+
+ DTV_KANTM_2G_STEPUP = 0,
+ DTV_KANTM_2G_STEPUP_KOR = 1,
+ DTV_KANTM_2_5G_STEPUP = 2,
+ DTV_KANTM_2_G_STEPUP_KOR = 3,
+ DTV_KANTM_3_G_PREMIUM = 4,
+
+ DTV_KANTM2_M2e_1_5G_STEP_UP = 10,
+ DTV_KANTM2_M2e_2G_STEP_UP = 11,
+ DTV_KANTM2_M2e_2_5G_PREMIUM = 12,
+ DTV_KANTM2_M2e_2_5G_PREMINUM_8K = 13,
+
+ DTV_KANTS_1G = DTV_KANTM_2G_STEPUP,
+ DTV_KANTS_1_5G = DTV_KANTM_2G_STEPUP_KOR,
+
+ DTV_MUSEL_1_5G = 20,
+ DTV_MUSEL_2G = 21,
+ DTV_MUSEM_2_5G = 22,
+ DTV_MUSEM_8K = 23,
+
+ DTV_NIKEL_1_5G = 30, /** 1.5G Single decoding */
+ DTV_NIKEL_2G = 31, /** 2G Dual decoding */
+ DTV_NIKEM_2_5G = 32, /** 2.5G Dual decoding */
+ DTV_NIKEM_8K = 33, /** 3G + 1.5G 8K */
+
+ LFD_NIKEM_2_5G = 232, /** 2.5G Triple decoding, LFD model */
+ LFD_NIKEM_8K = 233, /** 3G + 1.5G 8K Triple decoding, LFD model */
+
+ DTV_KANTSU2_FHD = 11, /** KanstSU2 FHD spec - The Frame 32" */
+
+ DTV_OSCAR_P = 40, /** Oscar-P 8K */
+
+ DTV_OSCAR_S = 1040, /** Oscar-S 8K */
+ DTV_KANTSU2e = 1041, /** KantSU2e - Single decoding */
+ DTV_KANTSU2e_2G = 1042, /** KantSU2e - Dual decoding */
+ DTV_KATNSU2e_2G_FHD = 1043 /** KantSU2e - Dual decoding FHD */
+};
+
+inline int GetTVPanelWidth() {
+ const char key_panel_width[] =
+ "com.samsung/featureconf/panel_resolution_width";
+ int panel_width = 0;
+ int info_ret = system_info_get_custom_int(key_panel_width, &panel_width);
+ if (info_ret != SYSTEM_INFO_ERROR_NONE) {
+ LOG(WARNING) << __func__ << "(System info error:" << info_ret
+ << ") Fail to get panel width!!";
+ return 0;
+ }
+
+ return panel_width;
+}
+
+inline int GetTVPanelHeight() {
+ const char key_panel_ht[] = "com.samsung/featureconf/panel_resolution_height";
+ int panel_height = 0;
+ int info_ret = system_info_get_custom_int(key_panel_ht, &panel_height);
+ if (info_ret != SYSTEM_INFO_ERROR_NONE) {
+ LOG(WARNING) << __func__ << "(System info error:" << info_ret
+ << ") Fail to get panel height!!";
+ return 0;
+ }
+
+ return panel_height;
+}
+
+inline int GetTVMaxFramerate() {
+ const char key_framerate[] = "com.samsung/featureconf/vp9_framerate_size";
+ int max_VP9_framerate = 0;
+ int info_ret = system_info_get_custom_int(key_framerate, &max_VP9_framerate);
+ if (info_ret != SYSTEM_INFO_ERROR_NONE) {
+ LOG(WARNING) << __func__ << "(System info error:" << info_ret
+ << ") Fail to get framerate!!";
+ return 0;
+ }
+ return max_VP9_framerate;
+}
+
+inline bool IsCuvaHDRSupported() {
+ const char key_cuva_hdr[] =
+ "com.samsung/featureconf/hdr.cuva_function_support";
+ bool support = false;
+ const int info_ret = system_info_get_custom_bool(key_cuva_hdr, &support);
+ if (info_ret != SYSTEM_INFO_ERROR_NONE) {
+ LOG(WARNING) << "(System info error:" << info_ret
+ << ") Fail to get hdr.cuva.functoin_support!!";
+ return false;
+ }
+
+ return support;
+}
+
+inline int GetTVMaxBitrate() {
+ const char key_bitrate[] = "com.samsung/featureconf/vp9_bitrate_size";
+ int max_VP9_bitrate = 0;
+ int info_ret = system_info_get_custom_int(key_bitrate, &max_VP9_bitrate);
+ if (info_ret != SYSTEM_INFO_ERROR_NONE) {
+ LOG(WARNING) << __func__ << "(System info error:" << info_ret
+ << ") Fail to get bitrate!!";
+ return 0;
+ }
+
+ return max_VP9_bitrate;
+}
+
+inline std::string GetTVChipset() {
+ const char key_chipset[] = "com.samsung/featureconf/product.chipset";
+ std::string chipset;
+ char* str = nullptr;
+ int ret = system_info_get_custom_string(key_chipset, &str);
+ if (ret != SYSTEM_INFO_ERROR_NONE) {
+ LOG(WARNING) << "Failed to get system info : " << key_chipset;
+ } else if (str) {
+ chipset = str;
+ free(str);
+ }
+ return chipset;
+}
+
+inline ResourceTableIndex GetResourceTableIndex() {
+ const char rm_tbl_id_path[] = "/proc/device-tree/resource-manager/rm_tbl_idx";
+ int rm_idx = -1; // negative values are not used in RM table index
+
+ std::ifstream f(rm_tbl_id_path, std::ifstream::in);
+
+ if (f.good()) {
+ f >> rm_idx;
+ } else {
+ LOG(WARNING) << "Cannot get RM idx";
+ }
+
+ return static_cast<ResourceTableIndex>(rm_idx);
+}
+
+inline bool isTVRotated() {
+ bool is_rotated = false;
+ const char feature[] = "com.samsung/featureconf/display_rotator_supported";
+ if (system_info_get_custom_bool(feature, &is_rotated) !=
+ SYSTEM_INFO_ERROR_NONE) {
+ LOG(ERROR) << "Fail to get system info: display_rotator_supported";
+ return false;
+ }
+ return is_rotated;
+}
+#endif
+#endif
#include "base/logging.h"
-#if defined(OS_TIZEN_TV_PRODUCT)
+#if BUILDFLAG(IS_TIZEN_TV)
#include <vconf/vconf_rtc.h>
#endif
void VconfHandle::Set(const char* value, const bool is_rtc) {
if (is_rtc) {
-#if defined(OS_TIZEN_TV_PRODUCT)
+#if BUILDFLAG(IS_TIZEN_TV)
vconf_set_str_rtc(vconf_key_.c_str(), value);
#else
LOG(ERROR) << "RunTimeCreated vconf is not supported";
void VconfHandle::Set(const std::string value, const bool is_rtc) {
if (is_rtc) {
-#if defined(OS_TIZEN_TV_PRODUCT)
+#if BUILDFLAG(IS_TIZEN_TV)
vconf_set_str_rtc(vconf_key_.c_str(), value.c_str());
#else
LOG(ERROR) << "RunTimeCreated vconf is not supported";
void VconfHandle::Set(const int value, const bool is_rtc) {
if (is_rtc) {
-#if defined(OS_TIZEN_TV_PRODUCT)
+#if BUILDFLAG(IS_TIZEN_TV)
vconf_set_int_rtc(vconf_key_.c_str(), value);
#else
LOG(ERROR) << "RunTimeCreated vconf is not supported";
void VconfHandle::Set(const bool value, const bool is_rtc) {
if (is_rtc) {
-#if defined(OS_TIZEN_TV_PRODUCT)
+#if BUILDFLAG(IS_TIZEN_TV)
vconf_set_bool_rtc(vconf_key_.c_str(), value);
#else
LOG(ERROR) << "RunTimeCreated vconf is not supported";