virtual void OnMrsUrlChange(const std::string& url){};
virtual void OnContentIdChange(const std::string& id){};
virtual void OnInitData(const std::vector<unsigned char>& init_data) = 0;
+
+ virtual void RequestPlay(){}
+ virtual void RequestPause(){}
+ virtual void RequestResume(){}
#endif
// Executed whenever the presentation duration changes.
void SetDecryptorHandle(eme::eme_decryptor_t decryptor);
void SetHasEncryptedListenerOrCdm(bool value);
void SetVideoVisibility(bool visible);
+
+ void RequestPlay() override;
+ void RequestPause() override;
+ void RequestResume() override;
#endif
// |enabled_track_ids| contains track ids of enabled audio tracks.
if (shared_state_.renderer)
shared_state_.renderer->SetVideoVisibility(visible);
}
+
+void PipelineImpl::RendererWrapper::RequestPlay() {
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+ main_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&PipelineImpl::RequestPlay, weak_pipeline_));
+}
+
+void PipelineImpl::RendererWrapper::RequestPause() {
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+ main_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&PipelineImpl::RequestPause, weak_pipeline_));
+}
+
+void PipelineImpl::RendererWrapper::RequestResume() {
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+ main_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&PipelineImpl::RequestResume, weak_pipeline_));
+}
#endif
void PipelineImpl::RendererWrapper::CreateRendererInternal(
base::BindOnce(&RendererWrapper::SetVideoVisibility,
base::Unretained(renderer_wrapper_.get()), visible));
}
+
+void PipelineImpl::RequestPlay() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ client_->RequestPlay();
+}
+
+void PipelineImpl::RequestPause() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ client_->RequestPause();
+}
+
+void PipelineImpl::RequestResume() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ client_->RequestResume();
+}
#endif
#if defined(TIZEN_MULTIMEDIA)
void OnInitData(const std::vector<unsigned char>& init_data);
void SetHasEncryptedListenerOrCdm(bool value) override;
void SetVideoVisibility(bool visible) override;
+
+ void RequestPlay();
+ void RequestPause();
+ void RequestResume();
#endif
void OnBufferingStateChange(BufferingState state,
BufferingStateChangeReason reason);
virtual void OnMrsUrlChange(const std::string& url){};
virtual void OnContentIdChange(const std::string& id){};
virtual void OnInitData(const std::vector<unsigned char>& init_data){};
+
+ virtual void RequestPlay(){}
+ virtual void RequestPause(){}
+ virtual void RequestResume(){}
#endif
// Executed when buffering state is changed. |reason| indicates the cause of
[EnableIf=is_tizen_tv]
OnContentIdChange(string id);
+
+ [EnableIf=is_tizen_tv]
+ RequestPlay();
+
+ [EnableIf=is_tizen_tv]
+ RequestPause();
+
+ [EnableIf=is_tizen_tv]
+ RequestResume();
};
// Extension of the mojo::Renderer communication layer for HLS and Android
virtual void SetActiveAudioTrack(int) {}
virtual void SetActiveVideoTrack(int) {}
virtual void SetPreferTextLanguage(const std::string&) {}
- virtual int GetVideoId() { return 0; }
virtual bool RegisterTimeline(const std::string& timeline_selector) {
return false;
}
OnEncryptedMediaInitData(media::EmeInitDataType::CENC, init_data);
}
+void WebMediaPlayerImpl::RequestPlay() {
+ client_->ResumePlayback();
+}
+
+void WebMediaPlayerImpl::RequestPause() {
+ client_->PausePlayback(WebMediaPlayerClient::PauseReason::kUnknown);
+}
+
+void WebMediaPlayerImpl::RequestResume() {
+ if (!pipeline_controller_->IsSuspended()) {
+ LOG(INFO) << __func__ << " Already resumed.";
+ return;
+ }
+ was_suspended_by_player_ = false;
+ Resume();
+}
+
void WebMediaPlayerImpl::SetVideoVisibility(bool visible) {
return pipeline_controller_->SetVideoVisibility(visible);
}
#endif
client_->PausePlayback(WebMediaPlayerClient::PauseReason::kUnknown);
client_->SuspendPlayer();
+
+#if BUILDFLAG(IS_TIZEN_TV)
+ UpdatePlayState();
+#endif
}
void WebMediaPlayerImpl::FullscreenModeToggled() {
LOG(INFO) << __func__ << ": must_suspend=" << must_suspend
<< ", idle_suspended=" << idle_suspended
+#if defined(TIZEN_MULTIMEDIA)
+ << ", was_suspended_by_player_=" << was_suspended_by_player_
+#endif
<< ", background_suspended=" << background_suspended
<< ", can_stay_suspended=" << can_stay_suspended
<< ", is_stale=" << is_stale
void OnMrsUrlChange(const std::string& url) override;
void OnContentIdChange(const std::string& id) override;
void OnInitData(const std::vector<unsigned char>& init_data) override;
+
+ void RequestPlay() override;
+ void RequestPause() override;
+ void RequestResume() override;
#endif
#if defined(SAMSUNG_ELEMENTARY_MEDIA_STREAM_SOURCE)
if (client_)
client_->OnInitData(init_data);
}
+
+void TizenRendererImpl::RequestPlay() {
+ if (client_extension_) {
+ client_extension_->RequestPlay();
+ }
+}
+
+void TizenRendererImpl::RequestPause() {
+ if (client_extension_) {
+ client_extension_->RequestPause();
+ }
+}
+
+void TizenRendererImpl::RequestResume() {
+ if (client_extension_) {
+ client_extension_->RequestResume();
+ }
+ media_player_->SetVolume(volume_);
+}
+
+void TizenRendererImpl::OnVideoRect(const gfx::RectF& video_rect) {
+ SetMediaGeometry(video_rect, media::VIDEO_ROTATION_0);
+}
+
#endif
void TizenRendererImpl::OnSeekableTimeChange(base::TimeDelta min_time,
void OnLivePlaybackComplete() override;
content::WebContentsDelegate* GetWebContentsDelegate() const override;
void OnInitData(const std::vector<unsigned char>& init_data) override;
+
+ void RequestPlay() override;
+ void RequestPause() override;
+ void RequestResume() override;
+ void OnVideoRect(const gfx::RectF& video_rect) override;
#endif
#if defined(TIZEN_TBM_SUPPORT)
void OnNewTbmFrameAvailable(uint32_t player_id,
DCHECK(media_task_runner_->BelongsToCurrentThread());
client_->OnContentIdChange(id);
}
+
+void MediaPlayerRendererClient::RequestPlay() {
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+ client_->RequestPlay();
+}
+
+void MediaPlayerRendererClient::RequestPause() {
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+ client_->RequestPause();
+}
+
+void MediaPlayerRendererClient::RequestResume() {
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+ client_->RequestResume();
+}
#endif
void MediaPlayerRendererClient::OnNewFrameAvailable(
int sync) override;
void OnMrsUrlChange(const std::string& url) override;
void OnContentIdChange(const std::string& id) override;
+
+ void RequestPlay() override;
+ void RequestPause() override;
+ void RequestResume() override;
#endif
void OnVideoSizeChange(const gfx::Size& size) override;
void OnBufferUpdate(base::TimeDelta time) override;
int sync) override {}
void OnMrsUrlChange(const std::string& url) override {}
void OnContentIdChange(const std::string& id) override {}
+ void RequestPlay() override {}
+ void RequestPause() override {}
+ void RequestResume() override {}
#if defined(ENABLE_AUTO_ZOOM)
void SetAiZoomSettings(const media::TizenAiZoomSettings& settings);
#endif // defined(ENABLE_AUTO_ZOOM)
#include "base/logging.h"
#include "base/no_destructor.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "media/base/efl/media_player_util_efl.h"
#include "media/base/video_codecs.h"
+#include "media/filters/hardware_resource_types.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "tizen_src/chromium_impl/media/filters/esplusplayer_util.h"
#include "tizen_src/chromium_impl/tizen/tizen_tv_platform.h"
}
std::vector<DecoderStatePtr> available_states;
std::string chipset = GetTVChipset();
- absl::optional<DecoderType> override_last_decoder;
for (auto& state : decoder_states_) {
const auto decoder_descriptor = state->GetVideoDescriptor();
if(!decoder_descriptor) {
if(fps > 60) {
if (state->GetDecoderType(kMainDecoder)) {
state->SetRequiresBothDecoders(true);
- override_last_decoder = kSubDecoder;
available_states.clear();
available_states.push_back(state);
LOG(INFO) << "HFR on Pontus/NikeM2 does not support dual decode for > 60FPS";
LOG(INFO) << "Previous last used decoder "
<< DecoderTypeToString(last_used_decoder_) << " new decoder "
<< DecoderTypeToString(state->GetDecoderType());
- last_used_decoder_ = override_last_decoder.value_or(state->GetDecoderType(kDecoders));
return state;
}
LOG(INFO) << "Broadcast in use ? " << broadcast_in_use;
LOG(INFO) << "Previous last used decoder "
<< DecoderTypeToString(last_used_decoder_) << " new decoder "
<< DecoderTypeToString(state->GetDecoderType());
- last_used_decoder_ = override_last_decoder.value_or(state->GetDecoderType(kDecoders));
return state;
}
if (!available_states.empty()) {
default:
for (auto& state : available_states) {
if (state->IsAcquired() == false) {
- last_used_decoder_ = override_last_decoder.value_or(state->GetDecoderType(kDecoders));
return state;
}
}
DecoderStatePtr HardwareResourceHelper::GetResource(DecoderType type) {
for (auto& state : decoder_states_) {
if (state->GetDecoderType(type) == type) {
- last_used_decoder_ = state->GetDecoderType();
return state;
}
}
}
}
-void HardwareResourceHelper::SetAcquired(DecoderType dec,
+void HardwareResourceHelper::SetAcquired(DecoderType dec_flag,
DecoderOwner new_owner) {
- for (auto& state : decoder_states_) {
- if (state->GetDecoderType(kDecoders) == (dec & kDecoders)) {
- LOG(INFO) << "Set acquired on decoder: " << DecoderTypeToString(dec);
- SetAcquired(state, new_owner);
- return;
+ for (auto dec : {kMainDecoder, kSubDecoder}) {
+ if ((dec & dec_flag) == 0)
+ continue;
+
+ for (auto& state : decoder_states_) {
+ if (state->GetDecoderType(kDecoders) == dec) {
+ LOG(INFO) << "Set acquired on decoder: " << DecoderTypeToString(dec);
+ SetAcquired(state, new_owner);
+ break;
+ }
}
}
}
state->Owner().Suspend();
}
state->Acquire(true, new_owner);
+
+ if (!new_owner.IsOwnerTheSame(DecoderOwner(BroadcastOwnsDecoder()))) {
+ last_used_decoder_ = state->GetDecoderType(kDecoders);
+ }
}
}
return (decoder_states_.size() == 2);
}
+bool HardwareResourceHelper::IsAnyDecoderAcquiredByBroadcast() const {
+ return broadcast_decoder_ != kNoneDecoder;
+}
+
DecoderStatePtr HardwareResourceHelper::GetFHDDecoder(DecoderType type) {
return DecoderStatePtr(new DecoderState(new VideoDecoderDescriptor(
type | kFHDDecoder, kFHDWidth, kFHDHeight, kMaxFPS,
void HandleBroadcastDecoder(int broadcast_decoder);
bool IsDualDecoding();
+ bool IsAnyDecoderAcquiredByBroadcast() const;
+
static DecoderStatePtr GetUHDDecoder(DecoderType type);
static DecoderStatePtr GetFHDDecoder(DecoderType type);
static DecoderStatePtr GetFHDDecoderKantSU2e(DecoderType type);
switch (operation) {
case OperationForData::PLAY:
is_paused_by_buffering_ = false;
- Play();
+ if (!is_paused_) {
+ Play();
+ }
break;
case OperationForData::PAUSE:
is_paused_by_buffering_ = true;
return;
}
- if (!result) {
- LOG_ID(ERROR, player_id_) << "OnPrepareComplete prepare_async failed.";
- GetMediaPlayerClient()->OnError(PIPELINE_ERROR_INITIALIZATION_FAILED);
- return;
- }
-
if (GetPlayerState() != ESPLUSPLAYER_STATE_READY) {
LOG_ID(ERROR, player_id_)
<< "Invalid state (" << GetString(GetPlayerState())
return;
}
+ if (!result) {
+ LOG_ID(ERROR, player_id_) << "OnPrepareComplete prepare_async failed.";
+ GetMediaPlayerClient()->OnError(PIPELINE_ERROR_INITIALIZATION_FAILED);
+ return;
+ }
+
LOG_ID(INFO, player_id_) << "(" << static_cast<void*>(this) << ") "
<< __func__ << " is_paused_ : " << is_paused_
<< " seek_position : " << seek_position_
#include "media/base/decoder_buffer.h"
#include "media/base/media_switches.h"
#include "media/base/renderer_client.h"
+#include "media/filters/hardware_resource_types.h"
+#include "third_party/blink/public/platform/web_application_type.h"
#include "tizen/system_info.h"
#include "tizen_src/chromium_impl/media/filters/media_player_tizen_client.h"
#include <drmdecrypt_api.h>
#include <malloc.h>
#include <player_internal.h>
+#include <array>
#include <ivideo-dp-control.hpp>
// define constant for mse timeline.
#define TIMELINESTATE 3
#define TIMELINEPAUSED true
+namespace {
+
+std::pair<uint32_t, uint32_t> GetHBBTvTAResolution(uint32_t width,
+ uint32_t height) {
+ // NOTE: HBBTV TA requires to play two videos on two different scalers at the
+ // same time. To achive this behavior we limit maximal resolution to
+ // the value which always allow two HW decoder playbacks.
+ return {std::min(static_cast<uint32_t>(kFHDVideoMaxWidth), width),
+ std::min(static_cast<uint32_t>(kFHDVideoMaxHeight), height)};
+}
+
// malloc_trim(0) will be called every 2 minutes.
const base::TimeDelta kMallocTrimInterval = base::TimeDelta::FromSeconds(120);
+// Only for HBBTV TA
+// Estimated pulling ZOrder interval time, to proceed a fastswitch.
+const base::TimeDelta kHbbTVZorderCheckInterval = base::Milliseconds(500);
+} // namespace
+
namespace media {
+
// Limit of platform player's total (audio and video) buffer size
// for encrypted content in bytes
const media::player_buffer_size_t kDRMPlayerTotalBufferSize = 10 * 1024 * 1024;
return;
}
- if (type == DemuxerStream::AUDIO && use_sw_audio_decoder_) {
+ if (type == DemuxerStream::AUDIO && UseSwAudioDecoding()) {
SetSwAudioDecoder();
}
}
bool MediaPlayerESPlusPlayerTV::Play() {
- auto td_ptr = suitable_decoder_.lock();
auto dec_name = content::kNoneDecoder;
+
+ auto td_ptr = suitable_decoder_.lock();
if (td_ptr) {
+ if (blink::IsHbbTV() /* && decoder_conflict_ */ && !IsPrepared()) {
+ DemuxerStream* stream = GetDemuxerStream(media::DemuxerStream::VIDEO);
+ if (stream) {
+ VideoDecoderConfig video_config = stream->video_decoder_config();
+ ChooseDecoderIfNeeded(video_config.codec(), true /* ignore_conflict */);
+ MediaPlayerESPlusPlayer::Prepare();
+ MediaPlayerESPlusPlayer::Play();
+ return true;
+ }
+ }
dec_name = td_ptr->GetDecoderType();
SetDecoderAcquired(td_ptr->GetDecoderType());
}
PrepareAIZoom();
#endif // defined(ENABLE_AUTO_ZOOM)
- if (blink::IsHbbTV() && !decoder_assigned_) {
+ if (blink::IsHbbTV()) {
+ // 1. Check if main decoder might be prepared without conflicting.
+ // 2. If 4K cannot be allocated, just delay preparing when |Play|
+ // or |PrepareToMediaSwitch| is called.
DemuxerStream* stream = GetDemuxerStream(media::DemuxerStream::VIDEO);
if (stream) {
VideoDecoderConfig video_config = stream->video_decoder_config();
ChooseDecoderIfNeeded(video_config.codec());
- if (auto td_ptr = suitable_decoder_.lock()) {
- decoder_assigned_ = true;
- }
+ }
+
+ if (IsHbbTvTaAllowed() && GetMediaPlayerClient()) {
+ GetMediaPlayerClient()->OnBufferingStateChange(
+ BUFFERING_HAVE_ENOUGH, BUFFERING_CHANGE_REASON_UNKNOWN);
+ }
+
+ const bool has_suitable_decoder = suitable_decoder_.lock() != nullptr;
+ if (!has_suitable_decoder || decoder_conflict_) {
+ LOG_ID(WARNING, player_id_)
+ << "Delaying |Prepare| to avoid resource conflict";
+ return;
}
}
+
MediaPlayerESPlusPlayer::Prepare();
}
+void MediaPlayerESPlusPlayerTV::PrepareToMediaSwitch() {
+ if (!IsHbbTvTaAllowed()) {
+ LOG_ID(ERROR, player_id_) << "HbbTV-TA is not allowed";
+ return;
+ }
+
+ LOG_ID(INFO, player_id_);
+ is_for_ta_ = true;
+
+ if (GetPlayerState() == ESPLUSPLAYER_STATE_NONE) {
+ LOG_ID(INFO, player_id_)
+ << "Initialization order was wrong, request resume.";
+ should_trigger_ta_zorder_checking_ = true;
+ GetMediaPlayerClient()->RequestResume();
+ return;
+ }
+
+ bool has_suitable_decoder = (suitable_decoder_.lock() != nullptr);
+ if (has_suitable_decoder && !decoder_conflict_ && !CanPrepare()) {
+ LOG_ID(INFO, player_id_)
+ << "Already prepared (or still preparing), continue.";
+ StartCheckingHbbTVZOrder();
+ return;
+ }
+
+ LOG_ID(INFO, player_id_) << "Not prepared, choose decoder again and prepare.";
+ DemuxerStream* stream = GetDemuxerStream(media::DemuxerStream::VIDEO);
+ if (stream) {
+ VideoDecoderConfig video_config = stream->video_decoder_config();
+ ChooseDecoderIfNeeded(video_config.codec(), true /* ignore_conflict */);
+ auto td_ptr = suitable_decoder_.lock();
+ if (!td_ptr) {
+ LOG_ID(ERROR, player_id_) << "No decoder assigned!";
+ return;
+ }
+ }
+
+ should_trigger_ta_zorder_checking_ = true;
+ MediaPlayerESPlusPlayer::Prepare();
+}
+
+void MediaPlayerESPlusPlayerTV::RequestPlay() {
+ LOG_ID(INFO, player_id_) << "(" << static_cast<void*>(this) << ")";
+ if (!is_for_ta_) {
+ LOG_ID(ERROR, player_id_)
+ << "This method should be called for HbbTV-TA only";
+ return;
+ }
+
+ if (!GetMediaPlayerClient()) {
+ LOG_ID(ERROR, player_id_)
+ << "(" << static_cast<void*>(this) << ") No media player client";
+ return;
+ }
+ Play();
+ should_trigger_ta_zorder_checking_ = false;
+ StopCheckingHbbTVZOrder();
+ if (!is_ta_geometry_set_) {
+ // Setting geometry if prepare was significantly delayed.
+ is_ta_geometry_set_ = true;
+ GetMediaPlayerClient()->OnVideoRect(video_rect_);
+ }
+ ForceVideoOrder(VideoOrder::kOnTop);
+ GetMediaPlayerClient()->RequestPlay();
+}
+
+void MediaPlayerESPlusPlayerTV::RequestPause() {
+ LOG_ID(INFO, player_id_) << "(" << static_cast<void*>(this) << ")";
+ if (!is_for_ta_) {
+ LOG_ID(ERROR, player_id_)
+ << "This method should be called for HbbTV-TA only";
+ return;
+ }
+
+ if (!GetMediaPlayerClient()) {
+ LOG_ID(ERROR, player_id_)
+ << "(" << static_cast<void*>(this) << ") No media player client";
+ return;
+ }
+ GetMediaPlayerClient()->RequestPause();
+ ForceVideoOrder(VideoOrder::kOnBottom);
+}
+
+void MediaPlayerESPlusPlayerTV::SetVideoRect(const gfx::RectF& video_rect) {
+ LOG_ID(INFO, player_id_) << "(" << static_cast<void*>(this) << ")";
+ video_rect_ = video_rect;
+}
+
void MediaPlayerESPlusPlayerTV::Release() {
LOG_ID(INFO, player_id_) << "(" << static_cast<void*>(this) << ") "
<< __func__;
}
}
+ if (is_for_ta_) {
+ std::tie(video_stream_info.max_width, video_stream_info.max_height) =
+ GetHBBTvTAResolution(video_stream_info.width, video_stream_info.height);
+ }
+
video_codec_ = video_config.codec();
if (hdr_info_.compare(video_config.hdr_info()) != 0) {
is_hdr_changed_ = true;
policy = ESPLUSPLAYER_RSC_ALLOC_EXCLUSIVE;
}
#endif // defined(TIZEN_MULTIMEDIA_MJPEG_SUPPORT)
- LOG_ID(INFO, player_id_) << " Set RM policy for Tbm:" << static_cast<int>(policy);
+ LOG_ID(INFO, player_id_) << " Set RM policy for Tbm:"
+ << static_cast<int>(policy);
auto error = esplusplayer_set_resource_allocate_policy(esplayer_, policy);
if (error != ESPLUSPLAYER_ERROR_TYPE_NONE) {
GetMediaPlayerClient()->NotifyPlaybackState(kPlaybackReady, player_id_);
MediaPlayerESPlusPlayer::OnPrepareComplete(result);
+
+ if (is_for_ta_ && result && should_trigger_ta_zorder_checking_) {
+ should_trigger_ta_zorder_checking_ = false;
+ StartCheckingHbbTVZOrder();
+ }
}
void MediaPlayerESPlusPlayerTV::OnError(
}
#endif // defined(ENABLE_AUTO_ZOOM)
-void MediaPlayerESPlusPlayerTV::SetAudioPreloading() {
- if (!content::HardwareResourceHelper::IsAudioPreloadingSupported()) {
- LOG_ID(INFO, GetPlayerId())
- << "Audio preloading not available at this board";
- return;
+void MediaPlayerESPlusPlayerTV::SetSwAudioDecoder() {
+ auto player_error = esplusplayer_set_audio_codec_type(
+ esplayer_, ESPLUSPLAYER_AUDIO_CODEC_TYPE_SW);
+ if (player_error != ESPLUSPLAYER_ERROR_TYPE_NONE) {
+ LOG_ID(ERROR, GetPlayerId())
+ << "esplusplayer_set_audio_codec_type failed, error code "
+ << player_error;
}
-#if TIZEN_VERSION_AT_LEAST(6, 5, 0)
- // Setting virtual main out for SW decoder
- const auto player_error = esplusplayer_set_audio_preloading(esplayer_);
+#if TIZEN_VERSION_AT_LEAST(6, 5, 0)
+ player_error = esplusplayer_set_alternative_audio_resource(
+ esplayer_, ESPLUSPLAYER_AUDIO_RESOURCE_SIMPLE_MIX_OUT);
if (player_error != ESPLUSPLAYER_ERROR_TYPE_NONE) {
- LOG_ID(ERROR, GetPlayerId())
- << "esplusplayer_set_audio_preloading failed, error code "
+ LOG_ID(INFO, GetPlayerId())
+ << "esplusplayer_set_alternative_audio_resource failed, error code: "
<< player_error;
- return;
}
- audio_preloading_set_ = true;
-#else
- LOG_ID(INFO, GetPlayerId())
- << "Audio preloading not available at this Tizen version";
-#endif
-}
-void MediaPlayerESPlusPlayerTV::SetSwAudioDecoder() {
- auto player_error = esplusplayer_set_audio_codec_type(
- esplayer_, ESPLUSPLAYER_AUDIO_CODEC_TYPE_SW);
+ player_error = esplusplayer_set_simple_mix_out_buffer_level(
+ esplayer_, ESPLUSPLAYER_SIMPLE_MIX_OUT_BUFFER_HIGH);
if (player_error != ESPLUSPLAYER_ERROR_TYPE_NONE) {
- LOG_ID(ERROR, GetPlayerId())
- << "esplusplayer_set_audio_codec_type failed, error code "
+ LOG_ID(INFO, GetPlayerId())
+ << "esplusplayer_set_simple_mix_out_buffer_level failed, error code: "
<< player_error;
}
+#endif
}
void MediaPlayerESPlusPlayerTV::SetHwAudioDecoder() {
}
}
-void MediaPlayerESPlusPlayerTV::ChooseDecoderIfNeeded(VideoCodec codec) {
+void MediaPlayerESPlusPlayerTV::ChooseDecoderIfNeeded(VideoCodec codec,
+ bool ignore_conflict) {
if (!blink::IsHbbTV())
return;
+ if (auto td_ptr = suitable_decoder_.lock())
+ SetDecoderReleased(td_ptr->GetDecoderType());
+
+ // Prevent checking ZOrder for invalid decoder.
+ StopCheckingHbbTVZOrder();
+
content::WebContentsDelegate* contents_delegate =
GetMediaPlayerClient()->GetWebContentsDelegate();
if (contents_delegate != nullptr)
auto fps = static_cast<int>(framerate);
const auto max_resolution =
GetMaxResolution(capi_media_format_video_.mime_type, is_video_hole_);
- const auto max_width = max_resolution.width();
- const auto max_height = max_resolution.height();
+ auto max_width = max_resolution.width();
+ auto max_height = max_resolution.height();
+ if (is_for_ta_) {
+ std::tie(max_width, max_height) =
+ GetHBBTvTAResolution(max_width, max_height);
+ }
suitable_decoder_ =
content::HardwareResourceHelper::Get().GetSuitableResource(
media::MediaType::Video, content::HWAquirePolicy::SWITCH, max_width,
max_height, fps, codec);
- if (auto td_ptr = suitable_decoder_.lock()) {
- auto dec_name = td_ptr->GetDecoderType();
-#if TIZEN_VERSION_AT_LEAST(6, 0, 0)
- if ((dec_name & content::kSubDecoder) == content::kSubDecoder) {
- LOG_ID(INFO, player_id_) << "SUB decoder is used for this " << this;
- // 1 = set all video resources(decoder/scaler) to sub resources
- esplusplayer_set_alternative_video_resource(esplayer_, 1);
- // Setting SW audio decoder for SUB video decoder content.
- if (contents_delegate && contents_delegate->UseSwAudioDecoding()) {
- LOG_ID(INFO, player_id_)
- << "SW audio decoder is used for this " << this;
- SetSwAudioDecoder();
- }
- } else if ((dec_name & content::kMainDecoder) == content::kMainDecoder) {
- LOG_ID(INFO, player_id_) << "MAIN decoder is used for this " << this;
- // 0 = set all video resources(decoder/scaler) to main resources
- esplusplayer_set_alternative_video_resource(esplayer_, 0);
- // If using SW audio decoding is possible. HW audio decoder
- // should be explicitly used for MAIN decoder.
- if (contents_delegate && contents_delegate->UseSwAudioDecoding()) {
- LOG_ID(INFO, player_id_)
- << "HW audio decoder is used for this " << this;
- SetHwAudioDecoder();
- }
- } else {
- LOG_ID(ERROR, GetPlayerId()) << "CANNOT USE ANY VIDEO DECODER";
- }
- // Setting virtual main out for both main and sub players.
- if (contents_delegate && contents_delegate->UseSwAudioDecoding()) {
- SetAudioPreloading();
+
+ auto td_ptr = suitable_decoder_.lock();
+
+ if (!td_ptr) {
+ LOG_ID(ERROR, GetPlayerId()) << "No suitable decoder found";
+ return;
+ }
+
+ // NOTE: Broadcast always uses HW, so we need to avoid also audio conflicts
+ const bool is_hw_audio_conflicted = GetMediaType() & MediaType::Audio &&
+ content::HardwareResourceHelper::Get()
+ .IsAnyDecoderAcquiredByBroadcast() &&
+ !UseSwAudioDecoding();
+ decoder_conflict_ = td_ptr->IsAcquired() || is_hw_audio_conflicted;
+ if (decoder_conflict_) {
+ LOG_ID(INFO, player_id_) << "Conflict:"
+ << " audio_conflicted=" << is_hw_audio_conflicted
+ << " video_conflicted=" << td_ptr->IsAcquired();
+ if (!ignore_conflict) {
+ LOG_ID(ERROR, player_id_)
+ << "Selected decoder but it's already acquired.";
+ return;
}
+ LOG_ID(INFO, player_id_)
+ << "Selected decoder with conflict, but we're force to ignore it.";
+ }
+
+ auto dec_name = td_ptr->GetDecoderType();
+#if TIZEN_VERSION_AT_LEAST(6, 0, 0)
+ constexpr int kAllResourcesForMain = 0;
+ constexpr int kAllResourcesForSub = 1;
+ if ((dec_name & content::kSubDecoder) == content::kSubDecoder) {
+ LOG_ID(INFO, player_id_) << "SUB decoder is used for this " << this;
+ // 1 = set all video resources(decoder/scaler) to sub resources
+ esplusplayer_set_alternative_video_resource(esplayer_, kAllResourcesForSub);
+ } else if ((dec_name & content::kMainDecoder) == content::kMainDecoder) {
+ LOG_ID(INFO, player_id_) << "MAIN decoder is used for this " << this;
+ // 0 = set all video resources(decoder/scaler) to main resources
+ esplusplayer_set_alternative_video_resource(esplayer_,
+ kAllResourcesForMain);
+ } else {
+ LOG_ID(ERROR, GetPlayerId()) << "CANNOT USE ANY VIDEO DECODER";
+ }
+
+ // Setting SW audio decoder and audio output with mixer.
+ if (UseSwAudioDecoding()) {
+ LOG_ID(INFO, player_id_) << "SW audio decoder is used for this " << this;
+ SetSwAudioDecoder();
+ }
#endif
- decoder_conflict_ = td_ptr->IsAcquired();
- if (!decoder_conflict_) {
- // is_notification_playback_ready_delayed_ = true;
- bool media_resource_acquired = false;
- GetMediaPlayerClient()->NotifyPlaybackState(
- kPlaybackVideoReady, GetPlayerId(), "", "", &media_resource_acquired,
- NULL, NULL, dec_name);
- if (!media_resource_acquired) {
- LOG_ID(INFO, GetPlayerId()) << "HbbTV media resource was not acquired";
- return;
- }
- SetDecoderAcquired(dec_name);
- }
+ bool media_resource_acquired = false;
+ GetMediaPlayerClient()->NotifyPlaybackState(
+ kPlaybackVideoReady, GetPlayerId(), "", "", &media_resource_acquired,
+ NULL, NULL, dec_name);
+ if (!media_resource_acquired) {
+ LOG_ID(INFO, GetPlayerId()) << "HbbTV media resource was not acquired";
+ return;
}
+
+ SetDecoderAcquired(dec_name);
}
void MediaPlayerESPlusPlayerTV::SetDecoderAcquired(
player_error = esplusplayer_deactivate_audio(esplayer_);
if (player_error != ESPLUSPLAYER_ERROR_TYPE_NONE) {
LOG_ID(ERROR, player_id_)
- << "Deactivate audio failed, error code "
- << player_error;
+ << "Deactivate audio failed, error code " << player_error;
return false;
}
audio_stream_activated_ = false;
#endif
}
+void MediaPlayerESPlusPlayerTV::ForceVideoOrder(VideoOrder videoOrder) {
+#if defined(TIZEN_VIDEO_HOLE) && TIZEN_VERSION_AT_LEAST(6, 0, 0)
+ auto decoder = suitable_decoder_.lock();
+ if (!decoder) {
+ return;
+ }
+
+ std::array<IVideoDpControl::PlaneZOrder, 2> order;
+ if (videoOrder == VideoOrder::kOnTop)
+ order = {IVideoDpControl::DP_PLANE_MSB, IVideoDpControl::DP_PLANE_SMB};
+ else
+ order = {IVideoDpControl::DP_PLANE_SMB, IVideoDpControl::DP_PLANE_MSB};
+
+ const auto dec_type = decoder->GetDecoderType(content::kDecoders);
+ errno_t ret{};
+ switch (dec_type) {
+ case content::kMainDecoder:
+ ret = IVideoDpControl::getInstance()->setZorder(order.at(0));
+ break;
+ case content::kSubDecoder:
+ ret = IVideoDpControl::getInstance()->setZorder(order.at(1));
+ break;
+ default:
+ LOG_ID(ERROR, player_id_) << "Decoder not distinguished:" << dec_type;
+ }
+ if (ret) {
+ LOG_ID(WARNING, player_id_) << "SetZOrder failed with error: " << ret;
+ }
+#endif
+}
+
#if defined(TIZEN_VIDEO_HOLE)
void MediaPlayerESPlusPlayerTV::SetVideoVisibility(bool visible) {
- if (!blink::IsHbbTV() || !is_video_hole_)
+ if (!blink::IsHbbTV() || !is_video_hole_ || is_for_ta_)
return;
#if TIZEN_VERSION_AT_LEAST(6, 0, 0)
if (auto td_ptr = suitable_decoder_.lock()) {
- if (td_ptr->GetDecoderType(content::kDecoders) == content::kMainDecoder &&
- td_ptr->GetDecoderType(content::kResolutions) == content::kFHDDecoder)
- return;
auto dec_type = td_ptr->GetDecoderType(content::kDecoders);
const unsigned int kFullVisibility = 255;
const unsigned int kNoVisibility = 0;
}
#endif
+bool MediaPlayerESPlusPlayerTV::IsHbbTvTaAllowed() const {
+ // HbbTV Targeted Advertisement is allowed only when SW audio decoding is set.
+ return blink::IsHbbTV() && UseSwAudioDecoding();
+}
+
+void MediaPlayerESPlusPlayerTV::StartCheckingHbbTVZOrder() {
+ if (!is_for_ta_) {
+ return;
+ }
+ if (hbbtv_zorder_checker_timer_.IsRunning())
+ return;
+
+ LOG_ID(INFO, player_id_) << __func__;
+ is_ta_geometry_set_ = false;
+ hbbtv_zorder_checker_timer_.Start(
+ FROM_HERE, kHbbTVZorderCheckInterval, this,
+ &MediaPlayerESPlusPlayerTV::OnCheckingHbbtvTVZorder);
+}
+
+void MediaPlayerESPlusPlayerTV::StopCheckingHbbTVZOrder() {
+ if (!hbbtv_zorder_checker_timer_.IsRunning())
+ return;
+
+ LOG_ID(INFO, player_id_) << __func__;
+ hbbtv_zorder_checker_timer_.Stop();
+}
+
+void MediaPlayerESPlusPlayerTV::OnCheckingHbbtvTVZorder() {
+ if (is_ta_geometry_set_)
+ return;
+
+ auto decoder = suitable_decoder_.lock();
+ if (!decoder) {
+ LOG_ID(WARNING, player_id_) << "No suitable decoder";
+ return;
+ }
+
+ constexpr int kMainPlane = 0;
+ constexpr int kSubPlane = 1;
+ int expected_zorder_on_top;
+ const auto dec_type = decoder->GetDecoderType(content::kDecoders);
+ if ((dec_type & content::kDecoders) == content::kSubDecoder) {
+ expected_zorder_on_top = kSubPlane;
+ } else if ((dec_type & content::kDecoders) == content::kMainDecoder) {
+ expected_zorder_on_top = kMainPlane;
+ } else {
+ LOG_ID(WARNING, player_id_)
+ << "Cannot understand a decoder type: " << dec_type;
+ return;
+ }
+
+ constexpr size_t kZOrderRawMinimalLength = 8;
+ unsigned char order[kZOrderRawMinimalLength];
+ auto error = IVideoDpControl::getInstance()->getZorderRaw(order);
+ if (error) {
+ LOG_ID(WARNING, player_id_) << "Cannot acquire ZORDER: " << strerror(error);
+ return;
+ }
+
+ auto ToText = [](int plane) -> std::string {
+ switch (plane) {
+ case kMainPlane:
+ return "MAIN-SUB-BG";
+ case kSubPlane:
+ return "SUB-MAIN-BG";
+ default:
+ return "UNACCEPTED";
+ }
+ };
+
+ LOG_ID(INFO, player_id_) << "ZOrder=" << ToText(order[0])
+ << " expected=" << ToText(expected_zorder_on_top);
+
+ if (expected_zorder_on_top == order[0]) {
+ LOG_ID(INFO, player_id_)
+ << "ZOrder updated. Changing a geometry in advance.";
+ is_ta_geometry_set_ = true;
+ hbbtv_zorder_checker_timer_.Stop();
+ ForceVideoOrder(VideoOrder::kOnBottom);
+ GetMediaPlayerClient()->OnVideoRect(video_rect_);
+ }
+}
+
+bool MediaPlayerESPlusPlayerTV::UseSwAudioDecoding() const {
+ content::WebContentsDelegate* contents_delegate =
+ GetMediaPlayerClient()->GetWebContentsDelegate();
+ if (!contents_delegate) {
+ LOG_ID(ERROR, player_id_) << "Invalid web contents delegate";
+ return false;
+ }
+ return contents_delegate->UseSwAudioDecoding();
+}
+
} // namespace media
const media::VideoDecoderConfig& video_config) override;
void InitializeStreamConfig(DemuxerStream::Type type) override;
bool SetBufferType(const media::VideoDecoderConfig&) override;
- void SetAudioPreloading();
void SetHwAudioDecoder();
void SetSwAudioDecoder();
- void ChooseDecoderIfNeeded(media::VideoCodec codec);
void SetTbmCallbackPolicy(const media::VideoDecoderConfig& video_config);
+ void ChooseDecoderIfNeeded(media::VideoCodec codec,
+ bool ignore_conflict = false);
+
+ void PrepareToMediaSwitch() override;
+ void RequestPlay() override;
+ void RequestPause() override;
+ void SetVideoRect(const gfx::RectF& video_rect) override;
private:
+ enum class VideoOrder { kOnTop, kOnBottom };
+
#if TIZEN_VERSION_AT_LEAST(6, 0, 0)
class DrmInfo {
public:
bool DeactivateAudioStreamIfNeeded();
bool ActivateAudioStreamIfNeeded();
+ void ForceVideoOrder(VideoOrder videoOrder);
+ bool IsHbbTvTaAllowed() const;
+ bool UseSwAudioDecoding() const;
+
+ void StartCheckingHbbTVZOrder();
+ void StopCheckingHbbTVZOrder();
+ void OnCheckingHbbtvTVZorder();
+
#if defined(ENABLE_AUTO_ZOOM)
void PrepareAIZoom();
#endif // defined(ENABLE_AUTO_ZOOM)
media::PipelineStatistics stats_;
bool enable_tbm_buffer_callback_{false};
- bool use_sw_audio_decoder_{false};
- bool use_sw_video_decoder_{false};
- bool audio_preloading_set_{false};
bool decoder_conflict_{true};
int cb_frame_width_{0};
int cb_frame_height_{0};
bool is_video_drm_eme_{false};
media::VideoCodec video_codec_{media::VideoCodec::kUnknown};
std::weak_ptr<content::DecoderState> suitable_decoder_;
- bool decoder_assigned_{false};
esplusplayer_video_stream_info capi_media_format_video_;
base::RepeatingTimer current_time_update_timer_;
base::RepeatingTimer malloc_trim_timer;
+ base::RepeatingTimer hbbtv_zorder_checker_timer_;
bool audio_stream_activated_{true};
+ gfx::RectF video_rect_;
+ bool is_for_ta_{false};
+ bool is_ta_geometry_set_{false};
+ bool should_trigger_ta_zorder_checking_{false};
+
#if defined(ENABLE_AUTO_ZOOM)
std::unique_ptr<AIZoomManager> ai_zoom_manager_;
std::optional<media::TizenAiZoomSettings> ai_zoom_settings_;
#if BUILDFLAG(IS_TIZEN_TV)
virtual void SetDecryptorHandle(eme::eme_decryptor_t decryptor) {}
virtual void SetHasEncryptedListenerOrCdm(bool value) {}
+ virtual void PrepareToMediaSwitch() {}
+ virtual void RequestPlay() {}
+ virtual void RequestPause() {}
+ virtual void SetVideoRect(const gfx::RectF& video_rect) {}
virtual void SetVideoVisibility(bool visible) {}
#endif
};
virtual void OnLivePlaybackComplete() = 0;
virtual content::WebContentsDelegate* GetWebContentsDelegate() const = 0;
virtual void OnInitData(const std::vector<unsigned char>& init_data) = 0;
+
+ virtual void RequestPlay();
+ virtual void RequestPause();
+ virtual void RequestResume();
+ virtual void OnVideoRect(const gfx::RectF& video_rect);
#endif
};
#include "public/ewk_media_subtitle_info_product.h"
#include "public/ewk_user_media_internal.h"
#include "third_party/blink/public/platform/web_media_player.h"
+#include "tizen_src/chromium_impl/media/filters/hardware_resource_helper.h"
+#include "tizen_src/chromium_impl/media/filters/media_player_registry.h"
#endif
#if defined(TIZEN_PEPPER_EXTENSIONS)
const char kReplaceWith[] = "_";
#if BUILDFLAG(IS_TIZEN_TV)
static const int kMousePressAndHoldTimeout = 500; // long press: 500ms
+const int kBroadcastPlayerId = 0;
#endif
#if BUILDFLAG(IS_TIZEN_DA)
Ewk_Media_Playback_Info* playback_info =
ewkMediaPlaybackInfoCreate(player_id, url, mime_type, decoder);
- LOG(INFO)
- << "player_id:" << player_id << ",state: " << state
- << "(0-load : 1-videoready : 2-ready : 3-start : 4-finish : 5-stop)";
+ LOG(INFO) << "player_id:" << player_id << ",state: " << state
+ << "(0-load : 1-videoready : 2-ready : 3-start : 4-finish : 5-stop)"
+ << ", decoder: " << static_cast<int>(decoder);
switch (state) {
case kPlaybackLoad:
SmartCallback<EWebViewCallbacks::PlaybackLoad>().call(
SmartCallback<EWebViewCallbacks::DeviceConnectionChanged>().call(
&device_type);
}
+
+void EWebView::SetNextPlayerForMediaSwitch(int player_id) {
+ LOG(INFO) << player_id;
+ if (!UseSwAudioDecoding()) {
+ LOG(ERROR) << "This method should be used for HbbTV-TA only";
+ return;
+ }
+
+ if (player_id == kBroadcastPlayerId) {
+ auto resource = content::HardwareResourceHelper::Get().GetResource(
+ content::kMainDecoder);
+ if (resource) {
+ resource->Owner().Suspend();
+ }
+ return;
+ }
+
+ auto player =
+ media::MediaPlayerRegistry::GetInstance()->GetMediaPlayer(player_id);
+ if (!player) {
+ LOG(ERROR) << "Player with id " << player_id << " is not found";
+ return;
+ }
+ player->PrepareToMediaSwitch();
+}
+
+void EWebView::VideoPlay(int player_id) {
+ LOG(INFO) << player_id;
+ if (!UseSwAudioDecoding()) {
+ LOG(ERROR) << "This method should be used for HbbTV-TA only";
+ return;
+ }
+
+ auto player =
+ media::MediaPlayerRegistry::GetInstance()->GetMediaPlayer(player_id);
+ if (!player) {
+ LOG(ERROR) << "Player with id " << player_id << " is not found";
+ return;
+ }
+ player->RequestPlay();
+}
+
+void EWebView::VideoPause(int player_id) {
+ LOG(INFO) << player_id;
+ if (!UseSwAudioDecoding()) {
+ LOG(ERROR) << "This method should be used for HbbTV-TA only";
+ return;
+ }
+
+ auto player =
+ media::MediaPlayerRegistry::GetInstance()->GetMediaPlayer(player_id);
+ if (!player) {
+ LOG(ERROR) << "Player with id " << player_id << " is not found";
+ return;
+ }
+ player->RequestPause();
+}
+
+void EWebView::SetVideoGeometry(int x, int y, int w, int h) {
+ if (!UseSwAudioDecoding()) {
+ LOG(ERROR) << "This method should be used for HbbTV-TA only";
+ return;
+ }
+
+ for (auto p : media::MediaPlayerRegistry::GetInstance()->GetMediaPlayers()) {
+ p.second->SetVideoRect(gfx::RectF(x, y, w, h));
+ }
+}
#endif
void EWebView::SetIMEWindow(void* window) {
uint32_t previous,
uint32_t current);
void NotifyMediaDeviceConnectionChanged(int device_type);
+
+ void SetNextPlayerForMediaSwitch(int player_id);
+ void VideoPlay(int player_id);
+ void VideoPause(int player_id);
+ void SetVideoGeometry(int x, int y, int w, int h);
#endif // IS_TIZEN_TV
void SetScriptsCanOpenWindows(bool);
#include "tizen_src/chromium_impl/base/tizen/resource_manager.h"
#include "tizen_src/chromium_impl/ui/ozone/platform/efl/efl_window.h"
#endif
+#if BUILDFLAG(IS_TIZEN_TV)
+#include "tizen_src/chromium_impl/tizen/tizen_tv_platform.h"
+#endif
static Eina_Bool _ewk_view_default_user_media_permission(
Evas_Object*, Ewk_User_Media_Permission_Request*, void*);
Ewk_Board_Decoding_Capabilities ewk_view_board_decoding_capabilities_get(
const Evas_Object* view)
{
- LOG_EWK_API_MOCKUP();
+#if BUILDFLAG(IS_TIZEN_TV)
+ // This one should be moved into HbbTV code.
+ auto DecodingCapabilities = []() -> Ewk_Board_Decoding_Capabilities {
+ const std::string chipset = GetTVChipset();
+ const ResourceTableIndex rt_idx = GetResourceTableIndex();
+ // 1x FHD decoder: KantS2
+ // 1x UHD decoder: NikeL 1.5G
+ if (chipset == "KANTS2" || rt_idx == ResourceTableIndex::DTV_NIKEL_1_5G) {
+ LOG(INFO) << "It is low-end board, do not use dual decoding";
+ return EWK_BOARD_DECODING_CAPABILITIES_SINGLE;
+ }
+ // 2x FHD decoder: KantSU2E
+ if (chipset == "KANTSU2E") {
+ LOG(INFO) << "It is KantSU2e, use 2x FHD decoders";
+ return EWK_BOARD_DECODING_CAPABILITIES_DOUBLE_FHD;
+ }
+ // 1x UHD, 1x FHD decoder: other boards
+ LOG(INFO) << "It is " << chipset << ", rt idx is "
+ << static_cast<int>(rt_idx) << ", use both decoders";
+ return EWK_BOARD_DECODING_CAPABILITIES_FHD_AND_UHD;
+ };
+
+ static Ewk_Board_Decoding_Capabilities board_decoding_capabilities =
+ DecodingCapabilities();
+ return board_decoding_capabilities;
+#else
+ LOG_EWK_API_MOCKUP("Only for Tizen TV.");
return EWK_BOARD_DECODING_CAPABILITIES_UNKNOWN;
+#endif
}
void ewk_view_next_player_for_media_switch_set(
Evas_Object* view,
int player_id)
{
- LOG_EWK_API_MOCKUP();
+#if BUILDFLAG(IS_TIZEN_TV)
+ LOG(INFO) << "Notify about media switch, next player id: " << player_id;
+ EWK_VIEW_IMPL_GET_OR_RETURN(view, impl);
+ impl->SetNextPlayerForMediaSwitch(player_id);
+#else
+ LOG_EWK_API_MOCKUP("Only for Tizen TV.");
+#endif // BUILDFLAG(IS_TIZEN_TV)
}
-void ewk_view_sw_audio_decoding_set(
- Evas_Object* view,
- Eina_Bool use_sw_audio_decoder)
-{
+void ewk_view_sw_audio_decoding_set(Evas_Object* view,
+ Eina_Bool use_sw_audio_decoder) {
+#if BUILDFLAG(IS_TIZEN_TV)
+ LOG(INFO) << "Use sw audio decoding: "
+ << static_cast<bool>(use_sw_audio_decoder);
+ EWK_VIEW_IMPL_GET_OR_RETURN(view, impl);
+ impl->SetUseSwAudioDecoding(use_sw_audio_decoder);
+#else
+ LOG_EWK_API_MOCKUP("Only for Tizen TV.");
+#endif // BUILDFLAG(IS_TIZEN_TV)
+}
+
+void ewk_view_sw_audio_volume(Evas_Object* view, double volume) {
LOG_EWK_API_MOCKUP();
}
Evas_Object* view,
Eina_Rectangle v_area)
{
- LOG_EWK_API_MOCKUP();
+#if BUILDFLAG(IS_TIZEN_TV)
+ LOG(INFO) << "Notify about geometry: " << v_area.x << ", " << v_area.y << " "
+ << v_area.w << "x" << v_area.h;
+ EWK_VIEW_IMPL_GET_OR_RETURN(view, impl);
+ impl->SetVideoGeometry(v_area.x, v_area.y, v_area.w, v_area.h);
+#else
+ LOG_EWK_API_MOCKUP("Only for Tizen TV.");
+#endif // BUILDFLAG(IS_TIZEN_TV)
}
void ewk_view_release_players(
Evas_Object* view,
int video_id)
{
- LOG_EWK_API_MOCKUP();
+#if BUILDFLAG(IS_TIZEN_TV)
+ LOG(INFO) << "Video play: " << video_id;
+ EWK_VIEW_IMPL_GET_OR_RETURN(view, impl);
+ impl->VideoPlay(video_id);
+#else
+ LOG_EWK_API_MOCKUP("Only for Tizen TV.");
+#endif // BUILDFLAG(IS_TIZEN_TV)
}
void ewk_view_player_pause(
Evas_Object* view,
int video_id)
{
- LOG_EWK_API_MOCKUP();
+#if BUILDFLAG(IS_TIZEN_TV)
+ LOG(INFO) << "Video pause: " << video_id;
+ EWK_VIEW_IMPL_GET_OR_RETURN(view, impl);
+ impl->VideoPause(video_id);
+#else
+ LOG_EWK_API_MOCKUP("Only for Tizen TV.");
+#endif // BUILDFLAG(IS_TIZEN_TV)
}
EXPORT_API void ewk_view_sw_audio_decoding_set(Evas_Object* view,
Eina_Bool use_sw_audio_decoder);
+/**
+ * Sets volume for player using sw decoder
+ * @param view View object
+ * @param volume value of volume level, range 0.0 - 1.0
+ */
+EXPORT_API void ewk_view_sw_audio_volume(Evas_Object* view, double volume);
+
/**
* Set visibility of video with player_id
*