1 // Copyright 2022 Samsung Electronics Inc. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "tizen_src/chromium_impl/media/filters/esplusplayer_util.h"
7 #include <vconf/vconf.h>
9 #include "base/json/json_reader.h"
10 #include "base/logging.h"
11 #include "tizen_src/chromium_impl/build/tizen_version.h"
13 #if BUILDFLAG(IS_TIZEN_TV)
14 #include <resource_center.h>
15 #include <ri-common-type.h>
16 #include <ri-module-api.h>
17 #include <tv-resource-information/ri-api.h>
18 #include <tv-resource-manager/rm_module_api.h>
19 #include "base/command_line.h"
20 #include "base/memory/ptr_util.h"
21 #include "content/public/common/content_switches.h"
22 #include "ewk/efl_integration/common/application_type.h"
23 #include "ewk/efl_integration/common/content_switches_efl.h"
24 #include "tizen_src/chromium_impl/tizen/tizen_tv_platform.h"
29 #define ENUM_CASE(x) \
36 constexpr gfx::Size kFHDVideoMaxSize(1920, 1080);
37 constexpr gfx::Size k4KVideoMaxSize(3840, 2160);
38 constexpr gfx::Size k8KVideoMaxSize(7680, 4320);
42 const char* GetString(media::BufferStatus status) {
44 ENUM_CASE(media::kBufferNone);
45 ENUM_CASE(media::kBufferUnderrun);
46 ENUM_CASE(media::kBufferMinThreshold);
47 ENUM_CASE(media::kBufferNormal);
48 ENUM_CASE(media::kBufferMaxThreshold);
49 ENUM_CASE(media::kBufferOverflow);
50 ENUM_CASE(media::kBufferAhead);
51 ENUM_CASE(media::kBufferEos);
53 NOTREACHED() << "Invalid BufferStatus (" << status << ")";
57 const char* GetString(esplusplayer_submit_status status) {
59 ENUM_CASE(ESPLUSPLAYER_SUBMIT_STATUS_NOT_PREPARED);
60 ENUM_CASE(ESPLUSPLAYER_SUBMIT_STATUS_INVALID_PACKET);
61 ENUM_CASE(ESPLUSPLAYER_SUBMIT_STATUS_OUT_OF_MEMORY);
62 ENUM_CASE(ESPLUSPLAYER_SUBMIT_STATUS_FULL);
63 ENUM_CASE(ESPLUSPLAYER_SUBMIT_STATUS_SUCCESS);
65 NOTREACHED() << "Invalid Submit Status (" << status << ")";
69 const char* GetString(esplusplayer_state state) {
71 ENUM_CASE(ESPLUSPLAYER_STATE_NONE);
72 ENUM_CASE(ESPLUSPLAYER_STATE_IDLE);
73 ENUM_CASE(ESPLUSPLAYER_STATE_READY);
74 ENUM_CASE(ESPLUSPLAYER_STATE_PLAYING);
75 ENUM_CASE(ESPLUSPLAYER_STATE_PAUSED);
76 ENUM_CASE(ESPLUSPLAYER_STATE_MAX);
78 NOTREACHED() << "Invalid state (" << state << ")";
82 esplusplayer_audio_mime_type ConvertToESPlusAudioMimeType(
83 media::AudioCodec codec) {
84 esplusplayer_audio_mime_type audioMimeType;
86 case media::AudioCodec::kAAC:
87 audioMimeType = ESPLUSPLAYER_AUDIO_MIME_TYPE_AAC;
89 case media::AudioCodec::kMP3:
90 audioMimeType = ESPLUSPLAYER_AUDIO_MIME_TYPE_MP3;
92 case media::AudioCodec::kOpus:
93 audioMimeType = ESPLUSPLAYER_AUDIO_MIME_TYPE_OPUS;
95 case media::AudioCodec::kPCM:
96 audioMimeType = ESPLUSPLAYER_AUDIO_MIME_TYPE_PCM_S16LE;
98 case media::AudioCodec::kVorbis:
99 audioMimeType = ESPLUSPLAYER_AUDIO_MIME_TYPE_VORBIS;
101 case media::AudioCodec::kEAC3:
102 audioMimeType = ESPLUSPLAYER_AUDIO_MIME_TYPE_EAC3;
104 case media::AudioCodec::kAC3:
105 audioMimeType = ESPLUSPLAYER_AUDIO_MIME_TYPE_AC3;
107 #if BUILDFLAG(IS_TIZEN_TV) && TIZEN_VERSION_AT_LEAST(8, 0, 0)
108 case media::AudioCodec::kFLAC:
109 audioMimeType = ESPLUSPLAYER_AUDIO_MIME_TYPE_FLAC;
113 LOG(WARNING) << "Unknown codec :" << codec << ". Returning MP3.";
114 audioMimeType = ESPLUSPLAYER_AUDIO_MIME_TYPE_MP3;
117 return audioMimeType;
120 esplusplayer_video_mime_type ConvertToESPlusVideoMimeType(
121 media::VideoCodec codec) {
122 esplusplayer_video_mime_type videoMimeType;
124 case media::VideoCodec::kH264:
125 videoMimeType = ESPLUSPLAYER_VIDEO_MIME_TYPE_H264;
127 case media::VideoCodec::kMPEG2:
128 videoMimeType = ESPLUSPLAYER_VIDEO_MIME_TYPE_MPEG2;
130 case media::VideoCodec::kMPEG4:
131 videoMimeType = ESPLUSPLAYER_VIDEO_MIME_TYPE_MPEG4;
133 case media::VideoCodec::kVP8:
134 videoMimeType = ESPLUSPLAYER_VIDEO_MIME_TYPE_VP8;
136 case media::VideoCodec::kVP9:
137 videoMimeType = ESPLUSPLAYER_VIDEO_MIME_TYPE_VP9;
139 case media::VideoCodec::kHEVC:
140 videoMimeType = ESPLUSPLAYER_VIDEO_MIME_TYPE_HEVC;
142 case media::VideoCodec::kAV1:
143 videoMimeType = ESPLUSPLAYER_VIDEO_MIME_TYPE_AV1;
146 LOG(WARNING) << "Unknown codec :" << codec << ". Returning H264.";
147 videoMimeType = ESPLUSPLAYER_VIDEO_MIME_TYPE_H264;
150 return videoMimeType;
153 int GetElementryStreamIndex(DemuxerStream::Type type) {
154 DCHECK(type == DemuxerStream::AUDIO || type == DemuxerStream::VIDEO);
157 case DemuxerStream::AUDIO:
159 case DemuxerStream::VIDEO:
162 LOG(ERROR) << "Stream type [" << type
163 << "] is not supported. Returning 0 (Audio type).";
168 DemuxerStream::Type GetDemuxerStreamType(
169 const esplusplayer_stream_type stream_type) {
170 switch (stream_type) {
171 case ESPLUSPLAYER_STREAM_TYPE_AUDIO:
172 return DemuxerStream::AUDIO;
173 case ESPLUSPLAYER_STREAM_TYPE_VIDEO:
174 return DemuxerStream::VIDEO;
176 return DemuxerStream::UNKNOWN;
180 esplusplayer_stream_type GetESPlusPlayerStreamType(DemuxerStream::Type type) {
182 case DemuxerStream::AUDIO:
183 return ESPLUSPLAYER_STREAM_TYPE_AUDIO;
184 case DemuxerStream::VIDEO:
185 return ESPLUSPLAYER_STREAM_TYPE_VIDEO;
187 return ESPLUSPLAYER_STREAM_TYPE_MAX;
191 PipelineStatus GetPipelineError(const esplusplayer_error_type error) {
192 if (error == ESPLUSPLAYER_ERROR_TYPE_NOT_SUPPORTED_AUDIO_CODEC ||
193 error == ESPLUSPLAYER_ERROR_TYPE_NOT_SUPPORTED_VIDEO_CODEC ||
194 error == ESPLUSPLAYER_ERROR_TYPE_NOT_SUPPORTED_FORMAT ||
195 error == ESPLUSPLAYER_ERROR_TYPE_NOT_SUPPORTED_FILE)
196 return DECODER_ERROR_NOT_SUPPORTED;
197 else if (error == ESPLUSPLAYER_ERROR_TYPE_INVALID_STATE)
198 return PIPELINE_ERROR_INVALID_STATE;
199 else if (error == ESPLUSPLAYER_ERROR_TYPE_OUT_OF_MEMORY)
200 return PIPELINE_ERROR_ABORT;
201 else if (error == ESPLUSPLAYER_ERROR_TYPE_CONNECTION_FAILED)
202 return PIPELINE_ERROR_NETWORK;
204 return PIPELINE_ERROR_DECODE;
207 bool isProductTypeSero() {
208 bool is_sero = false;
209 #if BUILDFLAG(IS_TIZEN_TV)
210 is_sero = isTVRotated();
213 LOG(INFO) << "This product type is " << (is_sero ? "a Sero" : "not a Sero");
217 #if BUILDFLAG(IS_TIZEN_TV) && TIZEN_VERSION_AT_LEAST(6, 0, 0)
218 gfx::Size GetDynamicMaxCodecResolution() {
221 int max_framerate = 0;
222 #if !defined(BUILD_CHROME)
224 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
225 switches::kTizenAppId);
227 std::string app_id = "";
230 // resource center returns decodeer ability not resolution (ex.1088)
231 // http://wiki.vd.sec.samsung.net/display/OSS/02.+Max+Resolution
232 if (rc_get_max_video_resolution(app_id.c_str(), &max_width, &max_height,
233 &max_framerate) < 0) {
234 LOG(ERROR) << "Getting max video resolution failed in multiview mode.";
235 return {kFHDVideoMaxWidth, kFHDVideoMaxHeight};
238 // H.264 has to be decoded by 4K decoder(dvde) in multiview mode
239 // to support below scenario.
240 // Left FHD@30 (TVPlus) | Right FHD@60 (AirPlay is placed at right always)
241 // Refer to http://wiki.vd.sec.samsung.net/display/OSS/10.+Resource+table
242 if (max_width >= k8KVideoMaxWidth) {
243 return k8KVideoMaxSize;
244 } else if (max_width >= k4KVideoMaxWidth && max_width < k8KVideoMaxWidth) {
245 return k4KVideoMaxSize;
247 return kFHDVideoMaxSize;
251 const char* GetRIVideoCodecName(esplusplayer_video_mime_type mime_type) {
253 case ESPLUSPLAYER_VIDEO_MIME_TYPE_AV1:
254 return RI_CODEC_NAME_AV1;
255 case ESPLUSPLAYER_VIDEO_MIME_TYPE_VP8:
256 return RI_CODEC_NAME_VP8;
257 case ESPLUSPLAYER_VIDEO_MIME_TYPE_VP9:
258 return RI_CODEC_NAME_VP9;
259 case ESPLUSPLAYER_VIDEO_MIME_TYPE_HEVC:
260 return RI_CODEC_NAME_HEVC;
261 case ESPLUSPLAYER_VIDEO_MIME_TYPE_H264:
262 return RI_CODEC_NAME_H264;
263 case ESPLUSPLAYER_VIDEO_MIME_TYPE_MJPEG:
264 return RI_CODEC_NAME_MJPEG;
271 gfx::Size GetMaxCodecResolutionRI(esplusplayer_video_mime_type mime_type,
272 bool is_video_hole) {
275 int max_framerate = 0;
276 const char* ri_video_codec = GetRIVideoCodecName(mime_type);
278 // In portrait mode adaptive streaming has some problem
279 // when changing a resolution so Sero uses dvde decoder
280 // for all kind of codecs.
281 // The dvde decoder doesn't support VP8 and WMV. It is Sero product spec.
282 if (!*ri_video_codec) {
283 if (isProductTypeSero()) {
284 return k4KVideoMaxSize;
286 return kFHDVideoMaxSize;
290 if (ri_video_codec == RI_CODEC_NAME_H264) {
291 if (is_video_hole && isProductTypeSero())
292 return k4KVideoMaxSize;
294 return kFHDVideoMaxSize;
297 if (ri_get_max_resolution(ri_video_codec, &max_width, &max_height,
298 &max_framerate) != RI_OK) {
299 LOG(WARNING) << "Failed to get video max information";
300 const auto panel_resolution = GetPanelResolution();
301 return {panel_resolution.width(), panel_resolution.height()};
304 if (max_width >= k8KVideoMaxWidth) {
305 max_width = k8KVideoMaxWidth;
306 max_height = k8KVideoMaxHeight;
307 } else if (max_width >= k4KVideoMaxWidth && max_width < k8KVideoMaxWidth) {
308 max_width = k4KVideoMaxWidth;
309 max_height = k4KVideoMaxHeight;
310 } else if (max_width >= kFHDVideoMaxWidth && max_width < k4KVideoMaxWidth) {
311 max_width = kFHDVideoMaxWidth;
312 max_height = kFHDVideoMaxHeight;
314 return {max_width, max_height};
318 gfx::Size GetMaxCodecResolution(esplusplayer_video_mime_type mime_type,
319 bool is_video_hole) {
320 #if BUILDFLAG(IS_TIZEN_TV) && TIZEN_VERSION_AT_LEAST(6, 0, 0)
321 if (media::IsMultiviewMode()) {
322 // Multiview specification:
323 // http://wiki.vd.sec.samsung.net/pages/viewpage.action?pageId=79211942
324 return GetDynamicMaxCodecResolution();
326 return GetMaxCodecResolutionRI(mime_type, is_video_hole);
329 case ESPLUSPLAYER_VIDEO_MIME_TYPE_AV1:
330 case ESPLUSPLAYER_VIDEO_MIME_TYPE_HEVC:
331 case ESPLUSPLAYER_VIDEO_MIME_TYPE_VP9:
332 return k8KVideoMaxSize;
333 case ESPLUSPLAYER_VIDEO_MIME_TYPE_H264:
334 // H.264 has to be decoded by dvde decoder in multiview mode
335 // to support below scenario.
336 // Left FHD@30 (TVPlus) | Right FHD@60 (AirPlay)
337 // Refer to http://wiki.vd.sec.samsung.net/display/OSS/10.+Resource+table
338 if (is_video_hole && isProductTypeSero())
339 return k4KVideoMaxSize;
341 return kFHDVideoMaxSize;
342 case ESPLUSPLAYER_VIDEO_MIME_TYPE_VP8:
344 // In portrait mode adaptive streaming has some problem
345 // when changing a resolution so Sero uses dvde decoder
346 // for all kind of codecs.
347 // The dvde decoder doesn't support VP8 and WMV. It is Sero product spec.
348 if (isProductTypeSero())
349 return k4KVideoMaxSize;
351 return kFHDVideoMaxSize;
356 gfx::Size GetPanelResolution() {
357 gfx::Size panel_size;
358 #if BUILDFLAG(IS_TIZEN_TV)
359 panel_size = gfx::Size(GetTVPanelWidth(), GetTVPanelHeight());
361 return panel_size.IsEmpty() ? kFHDVideoMaxSize : panel_size;
364 gfx::Size GetMaxResolution(esplusplayer_video_mime_type mime_type,
365 bool is_video_hole) {
366 const auto max_codec_resolution =
367 GetMaxCodecResolution(mime_type, is_video_hole);
368 const auto panel_resolution = GetPanelResolution();
369 return {std::min(max_codec_resolution.width(), panel_resolution.width()),
370 std::min(max_codec_resolution.height(), panel_resolution.height())};
373 esplusplayer_display_rotation_type ConvertToESPlusPlayerDisplayRotation(
377 return ESPLUSPLAYER_DISPLAY_ROTATION_TYPE_270;
379 return ESPLUSPLAYER_DISPLAY_ROTATION_TYPE_180;
381 return ESPLUSPLAYER_DISPLAY_ROTATION_TYPE_90;
383 return ESPLUSPLAYER_DISPLAY_ROTATION_TYPE_NONE;
387 #if BUILDFLAG(IS_TIZEN_TV)
388 bool IsMultiviewMode() {
389 const char vconf_multiview_info[] = "memory/multiscreen/info";
391 char* multiview_info = vconf_get_str(vconf_multiview_info);
392 if (multiview_info) {
393 auto multiview_info_value = base::JSONReader::Read(multiview_info);
394 free(multiview_info);
395 if (!multiview_info_value || !multiview_info_value->is_dict()) {
396 LOG(ERROR) << "read vconf multiview info failed";
400 base::Value::Dict& dict = multiview_info_value->GetDict();
402 const std::string* mode_value = dict.FindString("mode");
403 if (mode_value && *mode_value == "on") {
404 LOG(INFO) << "It is in multiview mode.";