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;
223 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
224 switches::kTizenAppId);
226 // resource center returns decodeer ability not resolution (ex.1088)
227 // http://wiki.vd.sec.samsung.net/display/OSS/02.+Max+Resolution
228 if (rc_get_max_video_resolution(app_id.c_str(), &max_width, &max_height,
229 &max_framerate) < 0) {
230 LOG(ERROR) << "Getting max video resolution failed in multiview mode.";
231 return {kFHDVideoMaxWidth, kFHDVideoMaxHeight};
234 // H.264 has to be decoded by 4K decoder(dvde) in multiview mode
235 // to support below scenario.
236 // Left FHD@30 (TVPlus) | Right FHD@60 (AirPlay is placed at right always)
237 // Refer to http://wiki.vd.sec.samsung.net/display/OSS/10.+Resource+table
238 if (max_width >= k8KVideoMaxWidth) {
239 return k8KVideoMaxSize;
240 } else if (max_width >= k4KVideoMaxWidth && max_width < k8KVideoMaxWidth) {
241 return k4KVideoMaxSize;
243 return kFHDVideoMaxSize;
247 const char* GetRIVideoCodecName(esplusplayer_video_mime_type mime_type) {
249 case ESPLUSPLAYER_VIDEO_MIME_TYPE_AV1:
250 return RI_CODEC_NAME_AV1;
251 case ESPLUSPLAYER_VIDEO_MIME_TYPE_VP8:
252 return RI_CODEC_NAME_VP8;
253 case ESPLUSPLAYER_VIDEO_MIME_TYPE_VP9:
254 return RI_CODEC_NAME_VP9;
255 case ESPLUSPLAYER_VIDEO_MIME_TYPE_HEVC:
256 return RI_CODEC_NAME_HEVC;
257 case ESPLUSPLAYER_VIDEO_MIME_TYPE_H264:
258 return RI_CODEC_NAME_H264;
259 case ESPLUSPLAYER_VIDEO_MIME_TYPE_MJPEG:
260 return RI_CODEC_NAME_MJPEG;
267 gfx::Size GetMaxCodecResolutionRI(esplusplayer_video_mime_type mime_type,
268 bool is_video_hole) {
271 int max_framerate = 0;
272 const char* ri_video_codec = GetRIVideoCodecName(mime_type);
274 // In portrait mode adaptive streaming has some problem
275 // when changing a resolution so Sero uses dvde decoder
276 // for all kind of codecs.
277 // The dvde decoder doesn't support VP8 and WMV. It is Sero product spec.
278 if (!*ri_video_codec) {
279 if (isProductTypeSero()) {
280 return k4KVideoMaxSize;
282 return kFHDVideoMaxSize;
286 if (ri_video_codec == RI_CODEC_NAME_H264) {
287 if (is_video_hole && isProductTypeSero())
288 return k4KVideoMaxSize;
290 return kFHDVideoMaxSize;
293 if (ri_get_max_resolution(ri_video_codec, &max_width, &max_height,
294 &max_framerate) != RI_OK) {
295 LOG(WARNING) << "Failed to get video max information";
296 const auto panel_resolution = GetPanelResolution();
297 return {panel_resolution.width(), panel_resolution.height()};
300 if (max_width >= k8KVideoMaxWidth) {
301 max_width = k8KVideoMaxWidth;
302 max_height = k8KVideoMaxHeight;
303 } else if (max_width >= k4KVideoMaxWidth && max_width < k8KVideoMaxWidth) {
304 max_width = k4KVideoMaxWidth;
305 max_height = k4KVideoMaxHeight;
306 } else if (max_width >= kFHDVideoMaxWidth && max_width < k4KVideoMaxWidth) {
307 max_width = kFHDVideoMaxWidth;
308 max_height = kFHDVideoMaxHeight;
310 return {max_width, max_height};
314 gfx::Size GetMaxCodecResolution(esplusplayer_video_mime_type mime_type,
315 bool is_video_hole) {
316 #if BUILDFLAG(IS_TIZEN_TV) && TIZEN_VERSION_AT_LEAST(6, 0, 0)
317 if (media::IsMultiviewMode()) {
318 // Multiview specification:
319 // http://wiki.vd.sec.samsung.net/pages/viewpage.action?pageId=79211942
320 return GetDynamicMaxCodecResolution();
322 return GetMaxCodecResolutionRI(mime_type, is_video_hole);
325 case ESPLUSPLAYER_VIDEO_MIME_TYPE_AV1:
326 case ESPLUSPLAYER_VIDEO_MIME_TYPE_HEVC:
327 case ESPLUSPLAYER_VIDEO_MIME_TYPE_VP9:
328 return k8KVideoMaxSize;
329 case ESPLUSPLAYER_VIDEO_MIME_TYPE_H264:
330 // H.264 has to be decoded by dvde decoder in multiview mode
331 // to support below scenario.
332 // Left FHD@30 (TVPlus) | Right FHD@60 (AirPlay)
333 // Refer to http://wiki.vd.sec.samsung.net/display/OSS/10.+Resource+table
334 if (is_video_hole && isProductTypeSero())
335 return k4KVideoMaxSize;
337 return kFHDVideoMaxSize;
338 case ESPLUSPLAYER_VIDEO_MIME_TYPE_VP8:
340 // In portrait mode adaptive streaming has some problem
341 // when changing a resolution so Sero uses dvde decoder
342 // for all kind of codecs.
343 // The dvde decoder doesn't support VP8 and WMV. It is Sero product spec.
344 if (isProductTypeSero())
345 return k4KVideoMaxSize;
347 return kFHDVideoMaxSize;
352 gfx::Size GetPanelResolution() {
353 gfx::Size panel_size;
354 #if BUILDFLAG(IS_TIZEN_TV)
355 panel_size = gfx::Size(GetTVPanelWidth(), GetTVPanelHeight());
357 return panel_size.IsEmpty() ? kFHDVideoMaxSize : panel_size;
360 gfx::Size GetMaxResolution(esplusplayer_video_mime_type mime_type,
361 bool is_video_hole) {
362 const auto max_codec_resolution =
363 GetMaxCodecResolution(mime_type, is_video_hole);
364 const auto panel_resolution = GetPanelResolution();
365 return {std::min(max_codec_resolution.width(), panel_resolution.width()),
366 std::min(max_codec_resolution.height(), panel_resolution.height())};
369 esplusplayer_display_rotation_type ConvertToESPlusPlayerDisplayRotation(
373 return ESPLUSPLAYER_DISPLAY_ROTATION_TYPE_270;
375 return ESPLUSPLAYER_DISPLAY_ROTATION_TYPE_180;
377 return ESPLUSPLAYER_DISPLAY_ROTATION_TYPE_90;
379 return ESPLUSPLAYER_DISPLAY_ROTATION_TYPE_NONE;
383 #if BUILDFLAG(IS_TIZEN_TV)
384 bool IsMultiviewMode() {
385 const char vconf_multiview_info[] = "memory/multiscreen/info";
387 char* multiview_info = vconf_get_str(vconf_multiview_info);
388 if (multiview_info) {
389 auto multiview_info_value = base::JSONReader::Read(multiview_info);
390 free(multiview_info);
391 if (!multiview_info_value || !multiview_info_value->is_dict()) {
392 LOG(ERROR) << "read vconf multiview info failed";
396 base::Value::Dict& dict = multiview_info_value->GetDict();
398 const std::string* mode_value = dict.FindString("mode");
399 if (mode_value && *mode_value == "on") {
400 LOG(INFO) << "It is in multiview mode.";