From 35ab37c378857d1282065aa4fd875c75974e62eb Mon Sep 17 00:00:00 2001 From: Umesh Kumar Patel Date: Thu, 16 Apr 2015 15:41:01 +0530 Subject: [PATCH] [M40 Merge][MM] GStreamer 1.2 Multimedia Support Following are the m40 patches merged MM Common: GST 1.2 Up version http://165.213.202.130/gerrit/#/c/75366/ Video corruption issue with AppSink http://165.213.202.130/gerrit/#/c/75610/ ME: Replace playbin with uridecodebin and fimcconvert http://165.213.202.130/gerrit/#/c/75740/ Buffered data indication is incorrect for Media Element. http://165.213.202.130/gerrit/#/c/75819/ HTML5 Video loadstart / progress event TCT fails http://165.213.202.130/gerrit/#/c/76213/ Use S/W codec for Media Element http://165.213.202.130/gerrit/#/c/76681/ MSE: S/W codec support for MSE http://165.213.202.130/gerrit/#/c/75777/ Fix video corruption when video resolution is changed http://165.213.202.130/gerrit/#/c/75828/ Youtube playback is not working with PIXMAP http://165.213.202.130/gerrit/#/c/76137/ Enabling MSE for desktop http://165.213.202.130/gerrit/#/c/76860/ WebRTC: Enable H/W accelerated H.264 support for WebRTC on Tizen http://165.213.202.130/gerrit/#/c/73796/ Change OMX control-rate from VBR to CBR http://165.213.202.130/gerrit/#/c/74361/ OMX codec integration on m0 target http://165.213.202.130/gerrit/#/c/75671/ Appsink implementation with fimcconvert http://165.213.202.130/gerrit/#/c/75791/ Memory leak fixes http://165.213.202.130/gerrit/#/c/76561/ Bug: http://web.sec.samsung.net/bugzilla/show_bug.cgi?id=12536 Bug: http://web.sec.samsung.net/bugzilla/show_bug.cgi?id=12777 Reviewed by: Antonio Gomes, Piotr Tworek, SeungSeop Park Change-Id: Icc88734422b24f684a49a3f27bb324ba6370f8fc Signed-off-by: Umesh Kumar Patel --- tizen_src/build/gyp_chromiumefl.sh | 7 +- .../browser/media/efl/browser_demuxer_efl.cc | 67 +- .../browser/media/efl/browser_demuxer_efl.h | 15 +- .../media/efl/browser_media_player_manager_efl.cc | 73 +- .../media/efl/browser_media_player_manager_efl.h | 46 +- .../efl/webaudio_decoder_browser_gstreamer.cc | 509 +++---- .../media/efl/webaudio_decoder_browser_gstreamer.h | 50 +- .../media/media_web_contents_observer_efl.cc | 51 +- .../media/media_web_contents_observer_efl.h | 14 +- .../media/efl/tizen_video_decode_accelerator.cc | 711 +++------ .../gpu/media/efl/tizen_video_decode_accelerator.h | 13 +- .../media/efl/tizen_video_encode_accelerator.cc | 444 +++--- .../gpu/media/efl/tizen_video_encode_accelerator.h | 6 +- .../common/media/efl/media_player_messages_efl.h | 75 +- .../content/common/message_generator_efl.h | 4 + .../renderer/media/efl/audio_decoder_gstreamer.h | 6 +- .../media/efl/media_source_delegate_efl.cc | 127 +- .../renderer/media/efl/media_source_delegate_efl.h | 47 +- .../renderer/media/efl/renderer_demuxer_efl.cc | 36 +- .../renderer/media/efl/renderer_demuxer_efl.h | 14 +- .../media/efl/renderer_media_player_manager_efl.cc | 152 +- .../media/efl/renderer_media_player_manager_efl.h | 68 +- .../chromium_impl/media/base/efl/demuxer_efl.h | 17 +- .../base/efl/demuxer_stream_player_params_efl.h | 6 +- .../base/efl/media_player_bridge_gstreamer.cc | 1299 ++++++++--------- .../media/base/efl/media_player_bridge_gstreamer.h | 83 +- .../media/base/efl/media_player_efl.h | 18 +- .../media/base/efl/media_player_manager_efl.h | 23 +- .../media/base/efl/media_player_util_efl.cc | 116 ++ .../media/base/efl/media_player_util_efl.h | 76 + .../base/efl/media_source_player_gstreamer.cc | 1524 +++++++------------- .../media/base/efl/media_source_player_gstreamer.h | 103 +- .../media/base/efl/webaudio_media_codec_info_efl.h | 6 +- .../media/base/efl/webmediaplayer_efl.cc | 194 ++- .../media/base/efl/webmediaplayer_efl.h | 53 +- tizen_src/chromium_impl/media/media_efl.gypi | 10 +- .../browser/render_message_filter_efl.cc | 23 +- 37 files changed, 2490 insertions(+), 3596 deletions(-) create mode 100644 tizen_src/chromium_impl/media/base/efl/media_player_util_efl.cc create mode 100644 tizen_src/chromium_impl/media/base/efl/media_player_util_efl.h diff --git a/tizen_src/build/gyp_chromiumefl.sh b/tizen_src/build/gyp_chromiumefl.sh index f8c319b..039ff72 100755 --- a/tizen_src/build/gyp_chromiumefl.sh +++ b/tizen_src/build/gyp_chromiumefl.sh @@ -60,7 +60,7 @@ COMMON_GYP_PARAMETERS=" -Duse_gnome_keyring=0 -Duse_openssl=1 -Duse_openssl_certs=1 - -Dtizen_multimedia_support=0 + -Dtizen_multimedia_eme_support=0 -Denable_plugins=1 -Denable_extensions=1 -Duse_cups=0 @@ -74,6 +74,7 @@ add_desktop_flags() { -Dbuilding_for_tizen_tv=0 -Dclang=${USE_CLANG} -Dtizen_multimedia_use_capi_for_me=0 + -Dtizen_multimedia_support=1 -Dwerror= " } @@ -102,10 +103,14 @@ add_tizen_flags() { " if [ "$tizen_version" == "2.2.1" -o "$tizen_version" == "2.3" ]; then + COMMON_GYP_PARAMETERS+="-Dtizen_multimedia_support=0 + " ADDITIONAL_GYP_PARAMETERS+="-Dlinux_use_gold_flags=0 -Dprebuilt_ld_gold_dir=${TOPDIR}/build/prebuild " else + COMMON_GYP_PARAMETERS+="-Dtizen_multimedia_support=1 + " ADDITIONAL_GYP_PARAMETERS+="-Dlinux_use_gold_flags=1 " fi diff --git a/tizen_src/chromium_impl/content/browser/media/efl/browser_demuxer_efl.cc b/tizen_src/chromium_impl/content/browser/media/efl/browser_demuxer_efl.cc index bf2d36f..11ed382 100644 --- a/tizen_src/chromium_impl/content/browser/media/efl/browser_demuxer_efl.cc +++ b/tizen_src/chromium_impl/content/browser/media/efl/browser_demuxer_efl.cc @@ -11,37 +11,31 @@ namespace content { class BrowserDemuxerEfl::Internal : public media::DemuxerEfl { public: Internal(const scoped_refptr& demuxer, - int demuxer_client_id) + int demuxer_client_id) : demuxer_(demuxer), - demuxer_client_id_(demuxer_client_id) { } + demuxer_client_id_(demuxer_client_id) {} - virtual ~Internal() { + ~Internal() override { DCHECK(ClientIDExists()) << demuxer_client_id_; demuxer_->RemoveDemuxerClient(demuxer_client_id_); } - // media::DemuxerEfl implementation. - virtual void Initialize(media::DemuxerEflClient* client) override { + // |media::DemuxerEfl| implementation. + void Initialize(media::DemuxerEflClient* client) override { DCHECK(!ClientIDExists()) << demuxer_client_id_; demuxer_->AddDemuxerClient(demuxer_client_id_, client); } - virtual void RequestDemuxerConfigs() override { + void RequestDemuxerData(media::DemuxerStream::Type type) override { DCHECK(ClientIDExists()) << demuxer_client_id_; - demuxer_->Send(new MediaPlayerGstMsg_MediaConfigRequest( - demuxer_client_id_)); - } - - virtual void RequestDemuxerData(media::DemuxerStream::Type type) override { - DCHECK(ClientIDExists()) << demuxer_client_id_; - demuxer_->Send(new MediaPlayerGstMsg_ReadFromDemuxer( + demuxer_->Send(new MediaPlayerEflMsg_ReadFromDemuxer( demuxer_client_id_, type)); } - virtual void RequestDemuxerSeek( + void RequestDemuxerSeek( const base::TimeDelta& time_to_seek) override { DCHECK(ClientIDExists()) << demuxer_client_id_; - demuxer_->Send(new MediaPlayerGstMsg_DemuxerSeekRequest( + demuxer_->Send(new MediaPlayerEflMsg_DemuxerSeekRequest( demuxer_client_id_, time_to_seek)); } @@ -57,8 +51,12 @@ class BrowserDemuxerEfl::Internal : public media::DemuxerEfl { DISALLOW_COPY_AND_ASSIGN(Internal); }; +scoped_refptr CreateBrowserDemuxerEfl() { + return new BrowserDemuxerEfl(); +} + BrowserDemuxerEfl::BrowserDemuxerEfl() - : BrowserMessageFilter(MediaPlayerEflMsgStart) {} + : BrowserMessageFilter(MediaPlayerMsgStart) {} BrowserDemuxerEfl::~BrowserDemuxerEfl() {} @@ -66,27 +64,27 @@ void BrowserDemuxerEfl::OverrideThreadForMessage( const IPC::Message& message, BrowserThread::ID* thread) { switch (message.type()) { - case MediaPlayerGstHostMsg_DemuxerReady::ID: - case MediaPlayerGstHostMsg_ReadFromDemuxerAck::ID: - case MediaPlayerGstHostMsg_BufferMetaDataAck::ID: - case MediaPlayerGstHostMsg_DurationChanged::ID: - case MediaPlayerGstHostMsg_DemuxerSeekDone::ID: + case MediaPlayerEflHostMsg_DemuxerReady::ID: + case MediaPlayerEflHostMsg_ReadFromDemuxerAck::ID: + case MediaPlayerEflHostMsg_DurationChanged::ID: + case MediaPlayerEflHostMsg_DemuxerSeekDone::ID: *thread = BrowserThread::UI; - return; + break; + default: + break; } } bool BrowserDemuxerEfl::OnMessageReceived(const IPC::Message& message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(BrowserDemuxerEfl, message) - IPC_MESSAGE_HANDLER(MediaPlayerGstHostMsg_DemuxerReady, OnDemuxerReady) - IPC_MESSAGE_HANDLER(MediaPlayerGstHostMsg_ReadFromDemuxerAck, + IPC_MESSAGE_HANDLER(MediaPlayerEflHostMsg_DemuxerReady, + OnDemuxerReady) + IPC_MESSAGE_HANDLER(MediaPlayerEflHostMsg_ReadFromDemuxerAck, OnReadFromDemuxerAck) - IPC_MESSAGE_HANDLER(MediaPlayerGstHostMsg_BufferMetaDataAck, - OnBufferMetaDataAck) - IPC_MESSAGE_HANDLER(MediaPlayerGstHostMsg_DurationChanged, + IPC_MESSAGE_HANDLER(MediaPlayerEflHostMsg_DurationChanged, OnDurationChanged) - IPC_MESSAGE_HANDLER(MediaPlayerGstHostMsg_DemuxerSeekDone, + IPC_MESSAGE_HANDLER(MediaPlayerEflHostMsg_DemuxerSeekDone, OnDemuxerSeekDone) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() @@ -102,14 +100,10 @@ scoped_ptr BrowserDemuxerEfl::CreateDemuxer( void BrowserDemuxerEfl::AddDemuxerClient( int demuxer_client_id, media::DemuxerEflClient* client) { - VLOG(1) << __FUNCTION__ << " peer_pid=" << peer_pid() - << " demuxer_client_id=" << demuxer_client_id; demuxer_clients_.AddWithID(client, demuxer_client_id); } void BrowserDemuxerEfl::RemoveDemuxerClient(int demuxer_client_id) { - VLOG(1) << __FUNCTION__ << " peer_pid=" << peer_pid() - << " demuxer_client_id=" << demuxer_client_id; demuxer_clients_.Remove(demuxer_client_id); } @@ -132,15 +126,6 @@ void BrowserDemuxerEfl::OnReadFromDemuxerAck( client->OnDemuxerDataAvailable(foreign_memory_handle, meta_data); } -void BrowserDemuxerEfl::OnBufferMetaDataAck( - int demuxer_client_id, - const media::DemuxedBufferMetaData& meta_data) { - media::DemuxerEflClient* client = - demuxer_clients_.Lookup(demuxer_client_id); - if (client) - client->OnBufferMetaDataAvailable( meta_data); -} - void BrowserDemuxerEfl::OnDemuxerSeekDone( int demuxer_client_id, const base::TimeDelta& actual_browser_seek_time) { diff --git a/tizen_src/chromium_impl/content/browser/media/efl/browser_demuxer_efl.h b/tizen_src/chromium_impl/content/browser/media/efl/browser_demuxer_efl.h index 65c6da3..77e7155 100644 --- a/tizen_src/chromium_impl/content/browser/media/efl/browser_demuxer_efl.h +++ b/tizen_src/chromium_impl/content/browser/media/efl/browser_demuxer_efl.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_BROWSER_MEDIA_TIZEN_BROWSER_DEMUXER_EFL_H_ -#define CONTENT_BROWSER_MEDIA_TIZEN_BROWSER_DEMUXER_EFL_H_ +#ifndef CONTENT_BROWSER_MEDIA_EFL_BROWSER_DEMUXER_EFL_H_ +#define CONTENT_BROWSER_MEDIA_EFL_BROWSER_DEMUXER_EFL_H_ #include "base/id_map.h" #include "base/memory/shared_memory.h" @@ -22,10 +22,10 @@ class CONTENT_EXPORT BrowserDemuxerEfl : public BrowserMessageFilter { BrowserDemuxerEfl(); // BrowserMessageFilter overrides. - virtual void OverrideThreadForMessage( + void OverrideThreadForMessage( const IPC::Message& message, BrowserThread::ID* thread) override; - virtual bool OnMessageReceived(const IPC::Message& message) override; + bool OnMessageReceived(const IPC::Message& message) override; // Returns an uninitialized demuxer implementation associated with // |demuxer_client_id|, which can be used to communicate with the real demuxer @@ -34,7 +34,7 @@ class CONTENT_EXPORT BrowserDemuxerEfl : public BrowserMessageFilter { protected: friend class base::RefCountedThreadSafe; - virtual ~BrowserDemuxerEfl(); + ~BrowserDemuxerEfl() override; private: class Internal; @@ -54,9 +54,6 @@ class CONTENT_EXPORT BrowserDemuxerEfl : public BrowserMessageFilter { int demuxer_client_id, base::SharedMemoryHandle foreign_memory_handle, const media::DemuxedBufferMetaData& meta_data); - void OnBufferMetaDataAck( - int demuxer_client_id, - const media::DemuxedBufferMetaData& meta_data); void OnDemuxerSeekDone( int demuxer_client_id, const base::TimeDelta& actual_browser_seek_time); @@ -71,4 +68,4 @@ class CONTENT_EXPORT BrowserDemuxerEfl : public BrowserMessageFilter { } // namespace content -#endif // CONTENT_BROWSER_MEDIA_TIZEN_BROWSER_DEMUXER_EFL_H_ +#endif // CONTENT_BROWSER_MEDIA_EFL_BROWSER_DEMUXER_EFL_H_ diff --git a/tizen_src/chromium_impl/content/browser/media/efl/browser_media_player_manager_efl.cc b/tizen_src/chromium_impl/content/browser/media/efl/browser_media_player_manager_efl.cc index b178e38..3fd87b9 100644 --- a/tizen_src/chromium_impl/content/browser/media/efl/browser_media_player_manager_efl.cc +++ b/tizen_src/chromium_impl/content/browser/media/efl/browser_media_player_manager_efl.cc @@ -34,19 +34,17 @@ BrowserMediaPlayerManagerEfl::BrowserMediaPlayerManagerEfl( } BrowserMediaPlayerManagerEfl::~BrowserMediaPlayerManagerEfl() { - for (ScopedVector::iterator it = players_.begin(); - it != players_.end(); ++it) { - (*it)->Destroy(); + for (auto& player : players_) { + player->Destroy(); } players_.weak_clear(); } media::MediaPlayerEfl* BrowserMediaPlayerManagerEfl::GetPlayer( int player_id) { - for (ScopedVector::iterator it = players_.begin(); - it != players_.end(); ++it) { - if ((*it)->GetPlayerId() == player_id) - return *it; + for (auto player : players_) { + if (player->GetPlayerId() == player_id) + return player; } return NULL; } @@ -55,7 +53,7 @@ void BrowserMediaPlayerManagerEfl::OnNewFrameAvailable( int player_id, base::SharedMemoryHandle foreign_memory_handle, uint32 length, base::TimeDelta timestamp) { - Send(new MediaPlayerGstMsg_NewFrameAvailable( + Send(new MediaPlayerEflMsg_NewFrameAvailable( GetRoutingID(), player_id, foreign_memory_handle, length, timestamp)); } @@ -64,80 +62,70 @@ void BrowserMediaPlayerManagerEfl::OnPlatformSurfaceUpdated( int player_id, int pixmap_id, base::TimeDelta timestamp) { - Send(new MediaPlayerGstMsg_PlatformSurfaceUpdated( + Send(new MediaPlayerEflMsg_PlatformSurfaceUpdated( GetRoutingID(), player_id, pixmap_id, timestamp)); } #endif void BrowserMediaPlayerManagerEfl::OnTimeChanged(int player_id) { - Send(new MediaPlayerGstMsg_TimeChanged(GetRoutingID(), player_id)); -} - -void BrowserMediaPlayerManagerEfl::OnPauseStateChange( - int player_id, - bool state) { - Send(new MediaPlayerGstMsg_OnPauseStateChange( - GetRoutingID(), player_id, state)); + Send(new MediaPlayerEflMsg_TimeChanged(GetRoutingID(), player_id)); } void BrowserMediaPlayerManagerEfl::OnSeekStateChange( int player_id, bool state) { - Send(new MediaPlayerGstMsg_OnSeekStateChange( - GetRoutingID(), player_id, state)); + Send(new MediaPlayerEflMsg_OnSeekStateChange( + GetRoutingID(), player_id, state)); } void BrowserMediaPlayerManagerEfl::OnRequestSeek( int player_id, double seek_time) { // To handle internal seek. - Send(new MediaPlayerGstMsg_SeekRequest( + Send(new MediaPlayerEflMsg_SeekRequest( GetRoutingID(), player_id, seek_time)); } void BrowserMediaPlayerManagerEfl::OnTimeUpdate( int player_id, double current_time) { - Send(new MediaPlayerGstMsg_TimeUpdate( + Send(new MediaPlayerEflMsg_TimeUpdate( GetRoutingID(), player_id, current_time)); } void BrowserMediaPlayerManagerEfl::OnBufferUpdate( int player_id, std::vector buffer_range) { - Send(new MediaPlayerGstMsg_BufferUpdate( + Send(new MediaPlayerEflMsg_BufferUpdate( GetRoutingID(), player_id, buffer_range)); } void BrowserMediaPlayerManagerEfl::OnDurationChange( int player_id, double duration) { - Send(new MediaPlayerGstMsg_DurationChanged( + Send(new MediaPlayerEflMsg_DurationChanged( GetRoutingID(), player_id, duration)); } void BrowserMediaPlayerManagerEfl::OnReadyStateChange( int player_id, media::MediaPlayerEfl::ReadyState state) { - Send(new MediaPlayerGstMsg_ReadyStateChange( + Send(new MediaPlayerEflMsg_ReadyStateChange( GetRoutingID(), player_id, state)); } void BrowserMediaPlayerManagerEfl::OnNetworkStateChange( int player_id, media::MediaPlayerEfl::NetworkState state) { - Send(new MediaPlayerGstMsg_NetworkStateChange( - GetRoutingID(), player_id, state)); + Send(new MediaPlayerEflMsg_NetworkStateChange( + GetRoutingID(), player_id, state)); } -void BrowserMediaPlayerManagerEfl::OnMediaDataChange( - int player_id, - int format, - int height, - int width, - int media) { - Send(new MediaPlayerGstMsg_MediaDataChanged( - GetRoutingID(), player_id, format, height, width, media)); +void BrowserMediaPlayerManagerEfl::OnMediaDataChange(int player_id, + int format, int height, + int width, int media) { + Send(new MediaPlayerEflMsg_MediaDataChanged(GetRoutingID(), player_id, + format, height, width, media)); } int BrowserMediaPlayerManagerEfl::GetRoutingID() { @@ -174,17 +162,20 @@ void BrowserMediaPlayerManagerEfl::OnInitialize( } else if (type == MEDIA_PLAYER_TYPE_MEDIA_SOURCE) { RenderProcessHostImpl* host = static_cast( web_contents()->GetRenderProcessHost()); + BrowserDemuxerEfl* browser_demuxer_efl = + static_cast(host->browser_demuxer_efl().get()); AddPlayer(new media::MediaSourcePlayerGstreamer( player_id, - host->browser_demuxer_efl()->CreateDemuxer(demuxer_client_id), + browser_demuxer_efl->CreateDemuxer(demuxer_client_id), this)); } else { LOG(ERROR) << __FUNCTION__ << " Load type is wrong!"; + OnNetworkStateChange( + player_id, media::MediaPlayerEfl::NetworkStateEmpty); } } void BrowserMediaPlayerManagerEfl::OnDestroy(int player_id) { - VLOG(1) << __FUNCTION__ << " " << player_id; RemovePlayer(player_id); } @@ -223,18 +214,13 @@ void BrowserMediaPlayerManagerEfl::OnSeek(int player_id, double time) { void BrowserMediaPlayerManagerEfl::AddPlayer( media::MediaPlayerEfl* player) { DCHECK(!GetPlayer(player->GetPlayerId())); - VLOG(1) << "BrowserMediaPlayerManagerEfl::" << __FUNCTION__ - << " Player-Id : " << player->GetPlayerId(); players_.push_back(player); } void BrowserMediaPlayerManagerEfl::RemovePlayer(int player_id) { - for (ScopedVector::iterator it = players_.begin(); - it != players_.end(); ++it) { + for (auto it = players_.begin(); it != players_.end(); ++it) { media::MediaPlayerEfl* player = *it; if (player->GetPlayerId() == player_id) { - VLOG(1) << "BrowserMediaPlayerManagerEfl::" << __FUNCTION__ - << " Player-Id : " << player->GetPlayerId(); players_.weak_erase(it); player->Destroy(); break; @@ -242,5 +228,4 @@ void BrowserMediaPlayerManagerEfl::RemovePlayer(int player_id) { } } -} // namespace content - +} // namespace content diff --git a/tizen_src/chromium_impl/content/browser/media/efl/browser_media_player_manager_efl.h b/tizen_src/chromium_impl/content/browser/media/efl/browser_media_player_manager_efl.h index 1178b69..c01d51d 100644 --- a/tizen_src/chromium_impl/content/browser/media/efl/browser_media_player_manager_efl.h +++ b/tizen_src/chromium_impl/content/browser/media/efl/browser_media_player_manager_efl.h @@ -2,10 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_BROWSER_MEDIA_TIZEN_BROWSER_MEDIA_PLAYER_MANAGER_TIZEN_H_ -#define CONTENT_BROWSER_MEDIA_TIZEN_BROWSER_MEDIA_PLAYER_MANAGER_TIZEN_H_ +#ifndef CONTENT_BROWSER_MEDIA_EFL_BROWSER_MEDIA_PLAYER_MANAGER_EFL_H_ +#define CONTENT_BROWSER_MEDIA_EFL_BROWSER_MEDIA_PLAYER_MANAGER_EFL_H_ #include "base/memory/scoped_vector.h" +#include "content/common/media/efl/media_player_messages_enums_efl.h" #include "content/public/browser/browser_message_filter.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents_observer.h" @@ -22,42 +23,35 @@ class CONTENT_EXPORT BrowserMediaPlayerManagerEfl : public media::MediaPlayerManager { public: // Returns a new instance using the registered factory if available. - static BrowserMediaPlayerManagerEfl* Create( RenderFrameHost* efh); - virtual ~BrowserMediaPlayerManagerEfl(); + static BrowserMediaPlayerManagerEfl* Create(RenderFrameHost* rfh); + ~BrowserMediaPlayerManagerEfl() override; // media::MediaPlayerManager implementation. - virtual media::MediaPlayerEfl* GetPlayer(int player_id) override; - virtual void OnTimeChanged(int player_id) override; - virtual void OnTimeUpdate(int player_id, double current_time) override; - virtual void OnPauseStateChange(int player_id, bool state) override; - virtual void OnSeekStateChange(int player_id, bool state) override; - virtual void OnRequestSeek(int player_id, double seek_time) override; - virtual void OnBufferUpdate( + media::MediaPlayerEfl* GetPlayer(int player_id) override; + void OnTimeChanged(int player_id) override; + void OnTimeUpdate(int player_id, double current_time) override; + void OnSeekStateChange(int player_id, bool state) override; + void OnRequestSeek(int player_id, double seek_time) override; + void OnBufferUpdate( int player_id, std::vector buffer_range) override; - virtual void OnDurationChange(int player_id, double duration) override; - virtual void OnReadyStateChange( + void OnDurationChange(int player_id, double duration) override; + void OnReadyStateChange( int player_id, media::MediaPlayerEfl::ReadyState state) override; - virtual void OnNetworkStateChange( + void OnNetworkStateChange( int player_id, media::MediaPlayerEfl::NetworkState state) override; - virtual void OnMediaDataChange( - int player_id, - int format, - int height, - int width, - int media) override; - virtual void OnNewFrameAvailable( + void OnMediaDataChange(int player_id, int format, int height, + int width, int media) override; + void OnNewFrameAvailable( int player_id, base::SharedMemoryHandle foreign_memory_handle, uint32 length, base::TimeDelta timestamp) override; #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) - virtual void OnPlatformSurfaceUpdated( - int player_id, - int pixmap_id, - base::TimeDelta timestamp) override; + void OnPlatformSurfaceUpdated(int player_id, int pixmap_id, + base::TimeDelta timestamp) override; #endif // Helper function to handle IPC from RenderMediaPlayerMangaerEfl. @@ -99,4 +93,4 @@ class CONTENT_EXPORT BrowserMediaPlayerManagerEfl } // namespace content -#endif // CONTENT_BROWSER_MEDIA_TIZEN_BROWSER_MEDIA_PLAYER_MANAGER_TIZEN_H_ +#endif // CONTENT_BROWSER_MEDIA_EFL_BROWSER_MEDIA_PLAYER_MANAGER_EFL_H_ diff --git a/tizen_src/chromium_impl/content/browser/media/efl/webaudio_decoder_browser_gstreamer.cc b/tizen_src/chromium_impl/content/browser/media/efl/webaudio_decoder_browser_gstreamer.cc index 1d0a6e0..891cdc3 100644 --- a/tizen_src/chromium_impl/content/browser/media/efl/webaudio_decoder_browser_gstreamer.cc +++ b/tizen_src/chromium_impl/content/browser/media/efl/webaudio_decoder_browser_gstreamer.cc @@ -4,11 +4,14 @@ #include "content/browser/media/efl/webaudio_decoder_browser_gstreamer.h" +#include +#include +#include +#include + #include "base/bind.h" #include "base/strings/string_util.h" #include "base/time/time.h" -#include "gst/app/gstappsink.h" -#include "gst/audio/audio.h" #include "media/base/audio_bus.h" #include "media/base/limits.h" #include "media/base/efl/webaudio_media_codec_info_efl.h" @@ -17,36 +20,72 @@ namespace content { #define CHUNK_SIZE 204800 // (4096*50) +#define GST_OBJECT_UNREF(obj) \ + if (obj) { \ + gst_object_unref(obj); \ + obj = NULL; \ + } static int gst_dec_count_ = 32; - -#if GST_VERSION_MAJOR == 1 static int audio_width_ = 16; -const char* kdecodebin = "decodebin"; -#endif -//////////////////////////////////////// +struct GstElementDeleter { + void operator()(GstElement* ptr) const { + GST_OBJECT_UNREF(ptr); + } +}; + // GSTDecoder class - declaration class GSTDecoder { public: + GSTDecoder(uint8_t* data, int pcm_output, uint32_t data_size); + ~GSTDecoder(); void InitializeGstDestination(int pcm_output, uint16_t number_of_channels, uint32_t sample_rate, size_t number_of_frames); void SendGstOutputUsinghandle(int pcm_output, uint8_t* buffer, int buf_size); - static void MediaFileDecoder(GstAppData* appData); + void MediaFileDecoder(); // callbacks - static void cb_newpad (GstElement* decodebin, GstPad* pad, GstAppData* data); - static void cb_need_data (GstElement* source, guint size, GstAppData* data); - static void cb_eos (GstAppSink* sink, gpointer user_data); - static GstFlowReturn cb_new_preroll (GstAppSink* sink, gpointer user_data); - static GstFlowReturn cb_new_buffer (GstAppSink* sink, gpointer user_data); - static GstBusSyncReply cb_pipeline_message (GstBus* bus, - GstMessage* message, - GstAppData* data); + static void OnNewPadAdded(GstElement* bin, GstPad* pad, + gpointer user_data); + static void OnNeedData(GstElement* source, guint size, gpointer user_data); + static void OnEOS(GstAppSink* sink, gpointer user_data); + static GstFlowReturn OnNewPreroll(GstAppSink* sink, gpointer user_data); + static GstFlowReturn OnNewBuffer(GstAppSink* sink, gpointer user_data); + static GstBusSyncReply OnBusMessage(GstBus* bus, GstMessage* message, + gpointer user_data); + private: + GstElement* app_src_; + GstElement* audioconvert_; + guint8* encodeddata_; + gsize enc_length_; + guint64 enc_offset_; + int pcm_output_; + bool is_running_; + bool is_endofstream_; + bool is_new_request_; }; // GSTDecoder class +GSTDecoder::GSTDecoder(uint8_t* data, int pcm_output, uint32_t data_size) + : app_src_(NULL), + audioconvert_(NULL), + encodeddata_(data), + enc_length_(data_size), + enc_offset_(0), + pcm_output_(pcm_output), + is_running_(true), + is_endofstream_(false), + is_new_request_(true) { + DCHECK(encodeddata_); +} + +GSTDecoder::~GSTDecoder() { + delete encodeddata_; + encodeddata_ = NULL; +} + void GSTDecoder::InitializeGstDestination(int pcm_output, uint16_t number_of_channels, uint32_t sample_rate, @@ -60,328 +99,253 @@ void GSTDecoder::InitializeGstDestination(int pcm_output, HANDLE_EINTR(write(pcm_output, &info, sizeof(info))); } -void GSTDecoder::SendGstOutputUsinghandle(int pcm_output, uint8_t * buffer, int buf_size) { +void GSTDecoder::SendGstOutputUsinghandle(int pcm_output, uint8_t* buffer, + int buf_size) { size_t count = buf_size; - ssize_t total_bytes = 0; while (count > 0) { int bytes_to_write = (count >= PIPE_BUF) ? PIPE_BUF : count; - ssize_t bytes_written = HANDLE_EINTR(write(pcm_output, buffer, bytes_to_write)); + ssize_t bytes_written = + HANDLE_EINTR(write(pcm_output, buffer, bytes_to_write)); if (bytes_written == -1) break; count -= bytes_written; buffer += bytes_written; - total_bytes += bytes_written; } return; } -void GSTDecoder::MediaFileDecoder(GstAppData* appData) { - if(!appData) - return; - +void GSTDecoder::MediaFileDecoder() { if (!gst_is_initialized()) { GError* err = NULL; if (!gst_init_check(NULL, NULL, &err)) { LOG(ERROR) << "Gst could not be initialized"; - close(appData->pcm_output_); + close(pcm_output_); return; } } - // makes gst-element(s) - appData->app_src_ = gst_element_factory_make("appsrc", NULL); - appData->app_sink_ = gst_element_factory_make("appsink", NULL); -#if GST_VERSION_MAJOR == 1 - appData->decoder_ = gst_element_factory_make(kdecodebin, NULL); -#else - appData->decoder_ = gst_element_factory_make("decodebin2", NULL); -#endif - appData->convert_ = gst_element_factory_make("audioconvert", NULL); - - appData->resample_ = gst_element_factory_make ("audioresample", NULL); - appData->capsfilter_ = gst_element_factory_make("capsfilter", NULL); -#if GST_VERSION_MAJOR == 1 - appData->caps_ = gst_caps_new_simple("audio/x-raw", "format", G_TYPE_STRING, - "S16LE", "rate", G_TYPE_INT, 44100, - "channels", G_TYPE_INT, 2, "layout", - G_TYPE_STRING, "interleaved", NULL); -#else - appData->caps_ = gst_caps_new_simple("audio/x-raw-int", "width", G_TYPE_INT, 16, NULL); -#endif - - if (!appData->app_src_ || !appData->app_sink_ || !appData->decoder_ || - !appData->convert_ || !appData->resample_ || !appData->capsfilter_ || - !appData->caps_) { - LOG(ERROR) << "Creation of one or more gst-element(s) for decoder pipeline failed"; + scoped_ptr pipeline; + gchar pipeline_name[16] = {0,}; + sprintf(pipeline_name, "pipeline_%d", gst_dec_count_); + + // makes gst-pipeline + pipeline.reset(gst_pipeline_new((const gchar*)&pipeline_name)); + GstBus* bus = NULL; + if (!(bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline.get())))) { + LOG(ERROR) << "GStreamer bus creation failed"; return; } + gst_bus_set_sync_handler( + bus, (GstBusSyncHandler)OnBusMessage, this, NULL); - g_object_set(G_OBJECT(appData->capsfilter_), "caps", appData->caps_, NULL); - gst_caps_unref(appData->caps_); + // App Src init + app_src_ = gst_element_factory_make("appsrc", NULL); + if (!gst_bin_add(GST_BIN(pipeline.get()), app_src_)) { + GST_OBJECT_UNREF(app_src_); + return; + } + g_signal_connect(app_src_, "need-data", G_CALLBACK(OnNeedData), this); - // sets propeties for element(s) - g_object_set(G_OBJECT(appData->app_sink_), "sync", FALSE, NULL); + // App Sink init + GstElement* app_sink = gst_element_factory_make("appsink", NULL); + if (!gst_bin_add(GST_BIN(pipeline.get()), app_sink)) { + GST_OBJECT_UNREF(app_sink); + return; + } + GstAppSinkCallbacks callbacks = {OnEOS, OnNewPreroll, OnNewBuffer}; + gst_app_sink_set_callbacks(GST_APP_SINK(app_sink), &callbacks, this, NULL); + g_object_set(G_OBJECT(app_sink), "sync", FALSE, NULL); + + // Decoder init + GstElement* decoder = gst_element_factory_make("decodebin", NULL); + if (!gst_bin_add(GST_BIN(pipeline.get()), decoder)) { + GST_OBJECT_UNREF(decoder); + return; + } + g_signal_connect(decoder, "pad-added", G_CALLBACK(OnNewPadAdded), this); - // connects signal(s) to element(s) - g_signal_connect(appData->app_src_, "need-data", G_CALLBACK(cb_need_data), appData); - g_signal_connect(appData->decoder_, "pad-added", G_CALLBACK(cb_newpad), appData); + // audio converter init + audioconvert_ = gst_element_factory_make("audioconvert", NULL); + if (!gst_bin_add(GST_BIN(pipeline.get()), audioconvert_)) { + GST_OBJECT_UNREF(audioconvert_); + return; + } -#if GST_VERSION_MAJOR == 1 - GstAppSinkCallbacks callbacks = { cb_eos, cb_new_preroll, - cb_new_buffer}; -#else - GstAppSinkCallbacks callbacks = { cb_eos, cb_new_preroll, - cb_new_buffer, NULL, - { NULL, NULL, NULL } }; -#endif - gst_app_sink_set_callbacks(GST_APP_SINK(appData->app_sink_), &callbacks, appData, NULL); + // Resample init + GstElement* sampler = gst_element_factory_make("audioresample", NULL); + if (!gst_bin_add(GST_BIN(pipeline.get()), sampler)) { + GST_OBJECT_UNREF(sampler); + return; + } - //FIXME: gst-element(s) can have 94 each name, but this can not be enough - gchar pipeline_name[16] = {0,}; - sprintf(pipeline_name, "pipeln_%d", gst_dec_count_); + // Capsfilter init + GstElement* capsfilter = gst_element_factory_make("capsfilter", NULL); + if (!gst_bin_add(GST_BIN(pipeline.get()), capsfilter)) { + GST_OBJECT_UNREF(capsfilter); + return; + } - memset(appData->audioout_name_, 0, 16); - sprintf(appData->audioout_name_, "audout_%d", gst_dec_count_); + GstCaps* caps = gst_caps_new_simple("audio/x-raw", + "format", G_TYPE_STRING, "S16LE", + "rate", G_TYPE_INT, 44100, + "channels", G_TYPE_INT, 2, + "layout", G_TYPE_STRING, "interleaved", + NULL); + + g_object_set(G_OBJECT(capsfilter), "caps", caps, NULL); + gst_caps_unref(caps); gst_dec_count_++; if (gst_dec_count_ > 126) gst_dec_count_ = 32; - // makes gst-pipeline - appData->pipeline_ = gst_pipeline_new((const gchar*)&pipeline_name); - gst_bin_add_many(GST_BIN(appData->pipeline_), appData->app_src_, appData->decoder_, NULL); - if (!gst_element_link(appData->app_src_, appData->decoder_)) { - LOG(ERROR) << __FUNCTION__ << " Something wrong on gst initialization"; - if ( appData->pipeline_ ) - gst_object_unref(appData->pipeline_); - return; - } - - // makes audio-output and links it to gst-pipeline - appData->audioout_ = gst_bin_new(appData->audioout_name_); - appData->audiopad_ = gst_element_get_static_pad(appData->convert_, "sink"); - - gst_bin_add_many(GST_BIN(appData->audioout_), appData->convert_, - appData->resample_, appData->capsfilter_, appData->app_sink_, NULL); - if (!gst_element_link_many(appData->convert_, appData->resample_, - appData->capsfilter_, appData->app_sink_, NULL)) { - LOG(ERROR) << __FUNCTION__ << "Some element could not be linked"; - if ( appData->pipeline_ ) - gst_object_unref(appData->pipeline_); + if (!gst_element_link(app_src_, decoder)) { + LOG(ERROR) << " Something wrong on gst initialization"; return; } - gst_element_add_pad(appData->audioout_, gst_ghost_pad_new("sink", appData->audiopad_)); - gst_object_unref(appData->audiopad_); - gst_bin_add(GST_BIN(appData->pipeline_), appData->audioout_); - - GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(appData->pipeline_)); - if (!bus) { - LOG(ERROR) << __FUNCTION__ << "GStreamer bus creation failed"; - if ( appData->pipeline_ ) - gst_object_unref(appData->pipeline_); + if (!gst_element_link_many(audioconvert_, sampler, + capsfilter, app_sink, NULL)) { + LOG(ERROR) << "Some element could not be linked"; return; } -#if GST_VERSION_MAJOR == 1 - gst_bus_set_sync_handler(bus, (GstBusSyncHandler)cb_pipeline_message, appData, - NULL); -#else - gst_bus_set_sync_handler(bus, (GstBusSyncHandler)cb_pipeline_message, appData); -#endif // actually works decoding - gst_element_set_state(appData->pipeline_, GST_STATE_PLAYING); + gst_element_set_state(pipeline.get(), GST_STATE_PLAYING); //FIXME: Check if its possible to remove usleep() and make any gst //async call so that GST wont block on Browser UI thread. - while (appData->isRunning_) { + while (is_running_) { usleep(10); } // returns resource(s) g_signal_handlers_disconnect_by_func( - bus, reinterpret_cast(cb_pipeline_message), appData); -#if GST_VERSION_MAJOR == 1 + bus, reinterpret_cast(OnBusMessage), this); gst_bus_set_sync_handler(bus, NULL, NULL, NULL); -#else - gst_bus_set_sync_handler(bus, NULL, NULL); -#endif - gst_object_unref(bus); - gst_element_set_state(appData->pipeline_, GST_STATE_NULL); - gst_object_unref(appData->pipeline_); + GST_OBJECT_UNREF(bus); + gst_element_set_state(pipeline.get(), GST_STATE_NULL); } -void GSTDecoder::cb_newpad(GstElement* decodebin, GstPad* pad, GstAppData* data) { -#if GST_VERSION_MAJOR == 1 - GstPad* sink_pad = gst_element_get_static_pad(data->audioout_, "sink"); -#else - GstPad* sink_pad = gst_element_get_pad(data->audioout_, "sink"); -#endif - if (GST_PAD_IS_LINKED(sink_pad)) { - g_object_unref(sink_pad); - return; - } - - GstCaps* caps = NULL; - GstStructure* str = NULL; - -#if GST_VERSION_MAJOR == 1 - caps = gst_pad_query_caps(pad, NULL); -#else - caps = gst_pad_get_caps(pad); -#endif - if (caps) { - str = gst_caps_get_structure(caps, 0); - if (str) { - if (!g_strrstr(gst_structure_get_name(str), data->audioout_name_)) - gst_pad_link(pad, sink_pad); - } +void GSTDecoder::OnNewPadAdded(GstElement* /*bin*/, GstPad* pad, + gpointer data) { + GSTDecoder* decoder = static_cast(data); + GstPad* sink_pad = gst_element_get_static_pad(decoder->audioconvert_, "sink"); + if (!GST_PAD_IS_LINKED(sink_pad)) { + gst_pad_link(pad, sink_pad); } g_object_unref(sink_pad); - gst_caps_unref(caps); } -void GSTDecoder::cb_need_data (GstElement* source, guint size, GstAppData* data) { - if (data->isEndOfStream_) +void GSTDecoder::OnNeedData(GstElement* /*source*/, guint /*size*/, + gpointer data) { + GSTDecoder* decoder = static_cast(data); + if (decoder->is_endofstream_) return; guint len = CHUNK_SIZE; - if ((data->enc_offset_ + len ) > data->enc_length_) - len = data->enc_length_ - data->enc_offset_; - -#if GST_VERSION_MAJOR == 1 - GstBuffer* buffer = gst_buffer_new_wrapped_full(GST_MEMORY_FLAG_READONLY, - data->encodeddata_ + data->enc_offset_, - len, 0, len, NULL, NULL); - if (!buffer) - { - LOG(ERROR) << __FUNCTION__ << "cb_need_data: buffer creation: FAILED"; + if ((decoder->enc_offset_ + len ) > decoder->enc_length_) + len = decoder->enc_length_ - decoder->enc_offset_; + + GstBuffer* buffer = + gst_buffer_new_wrapped_full(GST_MEMORY_FLAG_READONLY, + decoder->encodeddata_ + decoder->enc_offset_, + len, 0, len, NULL, NULL); + if (!buffer) { + LOG(ERROR) << "OnNeedData: buffer creation: FAILED"; return; } -#else - GstBuffer* buffer = gst_buffer_new(); - if (!buffer) - return; - - GST_BUFFER_DATA(buffer) = data->encodeddata_ + data->enc_offset_; - GST_BUFFER_SIZE(buffer) = len; -#endif - data->enc_offset_ += len; + decoder->enc_offset_ += len; GstFlowReturn ret = GST_FLOW_OK; - g_signal_emit_by_name(data->app_src_, "push-buffer", buffer, &ret); + g_signal_emit_by_name(decoder->app_src_, "push-buffer", buffer, &ret); if (ret != GST_FLOW_OK) { - LOG(ERROR) << "cb_need_data: push-buffer ret: FAILED"; - data->isRunning_ = false; + LOG(ERROR) << "OnNeedData: push-buffer ret: FAILED"; + decoder->is_running_ = false; } - if (data->enc_offset_ >= data->enc_length_) { - data->isEndOfStream_ = TRUE; - g_signal_emit_by_name(data->app_src_, "end-of-stream", &ret); + if (decoder->enc_offset_ >= decoder->enc_length_) { + decoder->is_endofstream_ = TRUE; + g_signal_emit_by_name(decoder->app_src_, "end-of-stream", &ret); } - gst_buffer_unref(buffer); } -void GSTDecoder::cb_eos (GstAppSink* sink, gpointer user_data) { - GstAppData* data = reinterpret_cast(user_data); - if (!data->isEndOfStream_) { +void GSTDecoder::OnEOS(GstAppSink* sink, gpointer data) { + GSTDecoder* decoder = static_cast(data); + if (!decoder->is_endofstream_) { LOG(ERROR) << "not end of stream yet appsrc-side"; } - close(data->pcm_output_); - data->isRunning_ = false; + close(decoder->pcm_output_); + decoder->is_running_ = false; } -GstFlowReturn GSTDecoder::cb_new_preroll (GstAppSink* sink, gpointer user_data) { +GstFlowReturn GSTDecoder::OnNewPreroll(GstAppSink*, gpointer) { return GST_FLOW_OK; } -GstFlowReturn GSTDecoder::cb_new_buffer (GstAppSink* sink, gpointer user_data) { -#if GST_VERSION_MAJOR == 1 +GstFlowReturn GSTDecoder::OnNewBuffer(GstAppSink* sink, gpointer data) { + GSTDecoder* decoder = static_cast(data); GstSample* sample = gst_app_sink_pull_sample(sink); + if (!sample) + return GST_FLOW_ERROR; + GstBuffer* buffer = gst_sample_get_buffer(sample); -#else - GstBuffer* buffer = gst_app_sink_pull_buffer(GST_APP_SINK(sink)); -#endif - if (!buffer) + if (!buffer) { + gst_sample_unref(sample); return GST_FLOW_ERROR; + } - GstAppData* data = (GstAppData*) (user_data); - - if (data->isNewRequest_) { + if (decoder->is_new_request_) { GstCaps* caps = NULL; GstStructure* str = NULL; -#if GST_VERSION_MAJOR == 1 - caps = gst_sample_get_caps(sample); -#else - caps = gst_buffer_get_caps(buffer); -#endif - if (caps) - str = gst_caps_get_structure(caps, 0); - gboolean ret = true; gint channel = 0; gint rate = 0; - gint width = 0; - if (caps && str) { - ret &= gst_structure_get_int(str, "channels", &channel); - ret &= gst_structure_get_int(str, "rate", &rate); -#if !(GST_VERSION_MAJOR == 1) - ret &= gst_structure_get_int(str, "width", &width); -#else - (void)width; -#endif + caps = gst_sample_get_caps(sample); + str = gst_caps_get_structure(caps, 0); + if (!caps || !str) { + gst_sample_unref(sample); + return GST_FLOW_ERROR; } + ret &= gst_structure_get_int(str, "channels", &channel); + ret &= gst_structure_get_int(str, "rate", &rate); -#if GST_VERSION_MAJOR == 1 - if (!caps || !str || !ret || !channel || !rate) { -#else - if (!caps || !str || !ret || !channel || !rate || !width) { -#endif - gst_caps_unref(caps); - gst_buffer_unref(buffer); + if (!ret || !channel || !rate) { + gst_sample_unref(sample); return GST_FLOW_ERROR; } -#if GST_VERSION_MAJOR == 1 - GstClockTime duration = (static_cast (gst_buffer_get_size(buffer)) - * 8 * GST_SECOND) / (channel * rate * audio_width_); -#else - GstClockTime duration = (static_cast (GST_BUFFER_SIZE(buffer))*8*GST_SECOND) - / (channel*rate*width); -#endif + GstClockTime duration = + (static_cast(gst_buffer_get_size(buffer)) * 8 * GST_SECOND) / + (channel * rate * audio_width_); int frames = GST_CLOCK_TIME_TO_FRAMES(duration, rate); - data->gst_decoder_->InitializeGstDestination(data->pcm_output_, channel, rate, frames); - data->isNewRequest_ = false; + decoder->InitializeGstDestination(decoder->pcm_output_, channel, + rate, frames); + decoder->is_new_request_ = false; } -#if GST_VERSION_MAJOR == 1 GstMapInfo gst_map; - gst_buffer_map(buffer, &gst_map, (GstMapFlags)(GST_MAP_READ)); - if (buffer && gst_map.size > 0) { - data->gst_decoder_->SendGstOutputUsinghandle(data->pcm_output_, - gst_map.data, - gst_map.size); + gst_buffer_map(buffer, &gst_map, static_cast(GST_MAP_READ)); + if (gst_map.size > 0) { + decoder->SendGstOutputUsinghandle(decoder->pcm_output_, + gst_map.data, + gst_map.size); gst_buffer_unmap(buffer, &gst_map); -#else - if (buffer && buffer->size > 0) { - data->gst_decoder_->SendGstOutputUsinghandle(data->pcm_output_, - buffer->data, - buffer->size); -#endif } - gst_buffer_unref(buffer); + gst_sample_unref(sample); return GST_FLOW_OK; } -GstBusSyncReply GSTDecoder::cb_pipeline_message(GstBus* bus, - GstMessage* message, - GstAppData* data) { +GstBusSyncReply GSTDecoder::OnBusMessage(GstBus* bus, + GstMessage* message, + gpointer data) { + GSTDecoder* decoder = static_cast(data); switch (GST_MESSAGE_TYPE(message)) { case GST_MESSAGE_ERROR: GError* error; @@ -391,93 +355,72 @@ GstBusSyncReply GSTDecoder::cb_pipeline_message(GstBus* bus, << ", error code : " << error->code; g_error_free(error); - if (data->isRunning_) { - close(data->pcm_output_); - data->isRunning_ = false; + if (decoder->is_running_) { + close(decoder->pcm_output_); + decoder->is_running_ = false; } break; default: - LOG(WARNING) << "Unhandled GStreamer message type : " - << GST_MESSAGE_TYPE_NAME(message); + DVLOG(1) << "Unhandled GStreamer message type : " + << GST_MESSAGE_TYPE_NAME(message); break; } - gst_message_unref(message); - return GST_BUS_DROP; } -//////////////////////////////////////// -// BrowserMessageFilterEfl class +// WebAudioDecoderGStreamer class // static -BrowserMessageFilterEfl* BrowserMessageFilterEfl::GetInstance() { - return Singleton::get(); +WebAudioDecoderGStreamer* WebAudioDecoderGStreamer::GetInstance() { + return Singleton::get(); } -BrowserMessageFilterEfl::BrowserMessageFilterEfl() +WebAudioDecoderGStreamer::WebAudioDecoderGStreamer() : gst_thread_("GstThread") { } -BrowserMessageFilterEfl::~BrowserMessageFilterEfl() { +WebAudioDecoderGStreamer::~WebAudioDecoderGStreamer() { } -void BrowserMessageFilterEfl::DecodeUsingGST( +void WebAudioDecoderGStreamer::DecodeUsingGST( base::SharedMemoryHandle foreign_memory_handle, base::FileDescriptor pcm_output, uint32_t data_size) { base::SharedMemory shared_memory(foreign_memory_handle, false); - shared_memory.Map(data_size); - - GstAppData* data = new GstAppData; - if (!data) + if (!shared_memory.Map(data_size)) { + LOG(ERROR) << "Failed to map shared memory for size " << data_size; return; + } - memset(data, 0, sizeof(GstAppData)); - - data->encodeddata_ = (uint8_t*) (malloc(data_size)); - if (!data->encodeddata_) { - LOG(ERROR) << "BrowserMessageFilterEfl::"<<__FUNCTION__ - << " - encodeddata malloc failed"; - delete data; + uint8_t* encoded_data = new uint8_t[data_size]; + if (!encoded_data) { + LOG(ERROR) << "Memory allocation failed for size = " << data_size; return; } - memcpy(data->encodeddata_, static_cast(shared_memory.memory()), data_size); - - data->isRunning_ = true; - data->enc_length_ = data_size; - data->pcm_output_ = pcm_output.fd; - data->isEndOfStream_ = false; - data->isNewRequest_ = true; - - GSTDecoder *decoder = new GSTDecoder(); - if (decoder) { - data->gst_decoder_ = decoder; - decoder->MediaFileDecoder(data); - delete decoder; - } - if (data->encodeddata_) { - free(data->encodeddata_); - data->encodeddata_ = NULL; - } - delete data; + memcpy(encoded_data, + static_cast(shared_memory.memory()), + data_size); + + // This will execute until decoding is done + GSTDecoder decoder(encoded_data, pcm_output.fd, data_size); + decoder.MediaFileDecoder(); } -void BrowserMessageFilterEfl::EncodedDataReceived( +void WebAudioDecoderGStreamer::EncodedDataReceived( base::SharedMemoryHandle foreign_memory_handle, base::FileDescriptor pcm_output, uint32_t data_size) { if (!gst_thread_.IsRunning() && !gst_thread_.Start()) { - LOG(ERROR) << "BrowserMessageFilterEfl::"<<__FUNCTION__ - << " - Starting GStreamer thread failed"; + LOG(ERROR) << "Starting GStreamer thread failed"; return; } gst_thread_.message_loop()->PostTask(FROM_HERE, - base::Bind(&BrowserMessageFilterEfl::DecodeUsingGST, + base::Bind(&WebAudioDecoderGStreamer::DecodeUsingGST, base::Unretained(this), foreign_memory_handle, pcm_output, data_size)); } diff --git a/tizen_src/chromium_impl/content/browser/media/efl/webaudio_decoder_browser_gstreamer.h b/tizen_src/chromium_impl/content/browser/media/efl/webaudio_decoder_browser_gstreamer.h index 019a0c6..75bc5d0 100644 --- a/tizen_src/chromium_impl/content/browser/media/efl/webaudio_decoder_browser_gstreamer.h +++ b/tizen_src/chromium_impl/content/browser/media/efl/webaudio_decoder_browser_gstreamer.h @@ -2,69 +2,39 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_BROWSER_MEDIA_TIZEN_WEBAUDIO_DECODER_BROWSER_GSTREAMER_H_ -#define CONTENT_BROWSER_MEDIA_TIZEN_WEBAUDIO_DECODER_BROWSER_GSTREAMER_H_ +#ifndef CONTENT_BROWSER_MEDIA_EFL_WEBAUDIO_DECODER_BROWSER_GSTREAMER_H_ +#define CONTENT_BROWSER_MEDIA_EFL_WEBAUDIO_DECODER_BROWSER_GSTREAMER_H_ #include "base/basictypes.h" #include "base/memory/singleton.h" #include "base/memory/shared_memory.h" #include "base/threading/thread.h" #include "content/common/content_export.h" -#include -#include namespace content { -class GSTDecoder; - -// GstAppData struct -typedef struct _GstAppData { - GstElement *pipeline_; - GstElement *app_src_, *app_sink_; - GstElement *decoder_, *convert_, *resample_, *capsfilter_; - GstCaps *caps_; - GstElement *audioout_; - GstElement *audio_; - GstPad *audiopad_; - - gchar audioout_name_[16]; - - bool isRunning_; - - guint sourceid_; // To control the GSource - guint8 *encodeddata_; - gsize enc_length_; - guint64 enc_offset_; - - int pcm_output_; - bool isEndOfStream_; - bool isNewRequest_; - - GSTDecoder *gst_decoder_; -} GstAppData; - -// BrowserMessageFilterEfl class -class CONTENT_EXPORT BrowserMessageFilterEfl { +// WebAudioDecoderGStreamer class +class WebAudioDecoderGStreamer { public: - static BrowserMessageFilterEfl* GetInstance(); + static WebAudioDecoderGStreamer* GetInstance(); void EncodedDataReceived(base::SharedMemoryHandle foreign_memory_handle, base::FileDescriptor pcm_output, uint32_t data_size); private: - friend struct DefaultSingletonTraits; - BrowserMessageFilterEfl(); - virtual ~BrowserMessageFilterEfl(); + friend struct DefaultSingletonTraits; + WebAudioDecoderGStreamer(); + virtual ~WebAudioDecoderGStreamer(); void DecodeUsingGST(base::SharedMemoryHandle foreign_memory_handle, base::FileDescriptor pcm_output, uint32_t data_size); base::Thread gst_thread_; - DISALLOW_COPY_AND_ASSIGN(BrowserMessageFilterEfl); + DISALLOW_COPY_AND_ASSIGN(WebAudioDecoderGStreamer); }; } // namespace content -#endif // CONTENT_BROWSER_MEDIA_TIZEN_WEBAUDIO_DECODER_BROWSER_GSTREAMER_H_ +#endif // CONTENT_BROWSER_MEDIA_EFL_WEBAUDIO_DECODER_BROWSER_GSTREAMER_H_ diff --git a/tizen_src/chromium_impl/content/browser/media/media_web_contents_observer_efl.cc b/tizen_src/chromium_impl/content/browser/media/media_web_contents_observer_efl.cc index 75b0750..025e131 100644 --- a/tizen_src/chromium_impl/content/browser/media/media_web_contents_observer_efl.cc +++ b/tizen_src/chromium_impl/content/browser/media/media_web_contents_observer_efl.cc @@ -13,68 +13,57 @@ namespace content { -MediaWebContentsObserverEfl::MediaWebContentsObserverEfl( - RenderViewHost* render_view_host) - : WebContentsObserver(WebContents::FromRenderViewHost(render_view_host)) { +MediaWebContentsObserver* CreateMediaWebContentsObserver( + WebContents* web_contents) { + return new MediaWebContentsObserver(web_contents); } -MediaWebContentsObserverEfl::~MediaWebContentsObserverEfl() { +MediaWebContentsObserver::MediaWebContentsObserver(WebContents* web_contents) + : WebContentsObserver(web_contents) { } -void MediaWebContentsObserverEfl::RenderFrameDeleted( +MediaWebContentsObserver::~MediaWebContentsObserver() { +} + +void MediaWebContentsObserver::RenderFrameDeleted( RenderFrameHost* render_frame_host) { uintptr_t key = reinterpret_cast(render_frame_host); media_player_managers_.erase(key); } -bool MediaWebContentsObserverEfl::OnMessageReceived(const IPC::Message& msg, - RenderFrameHost* render_frame_host) { - return OnMediaPlayerMessageReceived(msg, render_frame_host); -} - -bool MediaWebContentsObserverEfl::OnMediaPlayerMessageReceived( - const IPC::Message& msg, - RenderFrameHost* render_frame_host) { +bool MediaWebContentsObserver::OnMessageReceived( + const IPC::Message& msg, RenderFrameHost* render_frame_host) { bool handled = true; - - IPC_BEGIN_MESSAGE_MAP(MediaWebContentsObserverEfl, msg) - IPC_MESSAGE_FORWARD(MediaPlayerGstHostMsg_Init, + IPC_BEGIN_MESSAGE_MAP(MediaWebContentsObserver, msg) + IPC_MESSAGE_FORWARD(MediaPlayerEflHostMsg_Init, GetMediaPlayerManager(render_frame_host), BrowserMediaPlayerManagerEfl::OnInitialize) - - IPC_MESSAGE_FORWARD(MediaPlayerGstHostMsg_DeInit, + IPC_MESSAGE_FORWARD(MediaPlayerEflHostMsg_DeInit, GetMediaPlayerManager(render_frame_host), BrowserMediaPlayerManagerEfl::OnDestroy) - - IPC_MESSAGE_FORWARD(MediaPlayerGstHostMsg_Play, + IPC_MESSAGE_FORWARD(MediaPlayerEflHostMsg_Play, GetMediaPlayerManager(render_frame_host), BrowserMediaPlayerManagerEfl::OnPlay) - - IPC_MESSAGE_FORWARD(MediaPlayerGstHostMsg_Pause, + IPC_MESSAGE_FORWARD(MediaPlayerEflHostMsg_Pause, GetMediaPlayerManager(render_frame_host), BrowserMediaPlayerManagerEfl::OnPause) - - IPC_MESSAGE_FORWARD(MediaPlayerGstHostMsg_SetVolume, + IPC_MESSAGE_FORWARD(MediaPlayerEflHostMsg_SetVolume, GetMediaPlayerManager(render_frame_host), BrowserMediaPlayerManagerEfl::OnSetVolume) - - IPC_MESSAGE_FORWARD(MediaPlayerGstHostMsg_SetRate, + IPC_MESSAGE_FORWARD(MediaPlayerEflHostMsg_SetRate, GetMediaPlayerManager(render_frame_host), BrowserMediaPlayerManagerEfl::OnSetRate) - - IPC_MESSAGE_FORWARD(MediaPlayerGstHostMsg_Seek, + IPC_MESSAGE_FORWARD(MediaPlayerEflHostMsg_Seek, GetMediaPlayerManager(render_frame_host), BrowserMediaPlayerManagerEfl::OnSeek) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() return handled; } BrowserMediaPlayerManagerEfl* - MediaWebContentsObserverEfl::GetMediaPlayerManager( + MediaWebContentsObserver::GetMediaPlayerManager( RenderFrameHost* render_frame_host) { uintptr_t key = reinterpret_cast(render_frame_host); if (!media_player_managers_.contains(key)) { diff --git a/tizen_src/chromium_impl/content/browser/media/media_web_contents_observer_efl.h b/tizen_src/chromium_impl/content/browser/media/media_web_contents_observer_efl.h index 909a767..dbbe2a3 100644 --- a/tizen_src/chromium_impl/content/browser/media/media_web_contents_observer_efl.h +++ b/tizen_src/chromium_impl/content/browser/media/media_web_contents_observer_efl.h @@ -13,28 +13,22 @@ namespace content { class BrowserMediaPlayerManagerEfl; -class RenderViewHost; // This class manages all RenderFrame based media related managers at the // browser side. It receives IPC messages from media RenderFrameObservers and // forwards them to the corresponding managers. The managers are responsible // for sending IPCs back to the RenderFrameObservers at the render side. -class CONTENT_EXPORT MediaWebContentsObserverEfl +class CONTENT_EXPORT MediaWebContentsObserver : public WebContentsObserver { public: - explicit MediaWebContentsObserverEfl(RenderViewHost* render_view_host); - virtual ~MediaWebContentsObserverEfl(); + explicit MediaWebContentsObserver(WebContents* web_contents); + virtual ~MediaWebContentsObserver(); // WebContentsObserver implementations. virtual void RenderFrameDeleted(RenderFrameHost* render_frame_host) override; virtual bool OnMessageReceived(const IPC::Message& message, RenderFrameHost* render_frame_host) override; - // Helper functions to handle media player IPC messages. Returns whether the - // |message| is handled in the function. - bool OnMediaPlayerMessageReceived(const IPC::Message& message, - RenderFrameHost* render_frame_host); - // Gets the media player manager associated with |render_frame_host|. Creates // a new one if it doesn't exist. The caller doesn't own the returned pointer. BrowserMediaPlayerManagerEfl* GetMediaPlayerManager( @@ -46,7 +40,7 @@ class CONTENT_EXPORT MediaWebContentsObserverEfl MediaPlayerManagerMap; MediaPlayerManagerMap media_player_managers_; - DISALLOW_COPY_AND_ASSIGN(MediaWebContentsObserverEfl); + DISALLOW_COPY_AND_ASSIGN(MediaWebContentsObserver); }; } // namespace content diff --git a/tizen_src/chromium_impl/content/common/gpu/media/efl/tizen_video_decode_accelerator.cc b/tizen_src/chromium_impl/content/common/gpu/media/efl/tizen_video_decode_accelerator.cc index a7b7ce5..e25701c 100644 --- a/tizen_src/chromium_impl/content/common/gpu/media/efl/tizen_video_decode_accelerator.cc +++ b/tizen_src/chromium_impl/content/common/gpu/media/efl/tizen_video_decode_accelerator.cc @@ -9,23 +9,14 @@ #include #include #include +#include #include "base/bind.h" #include "base/memory/shared_memory.h" #include "base/message_loop/message_loop_proxy.h" +#include "base/process/process.h" #include "base/synchronization/waitable_event.h" #include "base/time/time.h" -#if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) -#include "ui/gl/efl_pixmap.h" -#else -#include "base/process/process.h" -#endif - -#if GST_VERSION_MAJOR == 1 -#include -#else -#include -#endif using media::VideoFrame; @@ -39,21 +30,16 @@ struct GstElementDeleter { }; // Gstreamer elements and names. -#if defined(OS_TIZEN) const char* kDecoderName = "decoder"; -#if GST_VERSION_MAJOR == 1 +const char* kParserElement = "h264parse"; +#if defined(TIZEN_MULTIMEDIA_USE_HW_CODEC) const char* kDecoderGstElement = "omxh264dec"; +const char* kVideoConvertElement = "fimcconvert"; +const char* kCapsFilterElement = "capsfilter"; #else -const char* kDecoderGstElement = "omx_h264dec"; +const char* kDecoderGstElement = "avdec_h264"; #endif -#endif // OS_TIZEN -// Generating Unique Key from given width and height. -#if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) -int32 ConvertWidthAndHeightToKey(int width, int height) { - return ((width << 16) | height); -} -#endif // TIZEN_MULTIMEDIA_PIXMAP_SUPPORT } // namespace namespace content { @@ -84,14 +70,14 @@ struct TizenVideoDecodeAccelerator::BitstreamBufferRef { gst_buffer_(NULL) {} ~BitstreamBufferRef() { - if (input_id_ >= 0) { - client_message_loop_proxy_->PostTask( - FROM_HERE, - base::Bind( - &media::VideoDecodeAccelerator::Client::NotifyEndOfBitstreamBuffer, - client_, - input_id_)); - } + if (input_id_ < 0) + return; + client_message_loop_proxy_->PostTask( + FROM_HERE, + base::Bind( + &media::VideoDecodeAccelerator::Client::NotifyEndOfBitstreamBuffer, + client_, + input_id_)); } static void Destruct(gpointer data) { @@ -118,33 +104,16 @@ struct TizenVideoDecodeAccelerator::Impl { appsrc_(NULL), io_message_loop_proxy_(base::MessageLoopProxy::current()), gst_thread_("TizenDecoderThreadGst"), - bitstream_buffer_id_(0) -#if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) - ,pixmap_id_(0), - gst_width_(0), - gst_height_(0), - damage_(0), - damage_handler_(NULL), - is_x_window_handle_set_(false) -#else - ,caps_width_(0), - caps_height_(0) -#endif -{ -#if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) - xpixmap_buffer_map_.clear(); -#endif -} + bitstream_buffer_id_(0), + caps_width_(0), + caps_height_(0) {} -#if !defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) + void DeliverVideoFrame(GstSample* sample, gfx::Rect frame_size); + bool CreateAppSrcElement(); + bool CreateAppSinkElement(); static GstFlowReturn OnDecoded(GstAppSink* sink, gpointer app_data); - void DeliverVideoFrame(GstBuffer* buffer, - int32 bitstream_buffer_id, - gfx::Rect frame_size); - void CreateAppSinkElement(); - static void OnSinkCapChanged( - GstPad* sink_pad, GParamSpec* gparamspec, void* user_data); -#endif + static void OnSinkCapsChanged(GstPad* sink_pad, GParamSpec* gparamspec, + void* user_data); static GstBusSyncReply OnBusMessage( GstBus* bus, GstMessage* msg, gpointer data) { @@ -153,70 +122,35 @@ struct TizenVideoDecodeAccelerator::Impl { gchar* debug = NULL; GError* error = NULL; gst_message_parse_error(msg, &error, &debug); - LOG(ERROR) << __FUNCTION__ - << " GSTError happens from bus at " + LOG(ERROR) << " GSTError happens from bus at " << GST_OBJECT_NAME(msg->src) << ":" << error->message; - LOG(ERROR) << __FUNCTION__ - << " Debugging Info: " + LOG(ERROR) << " Debugging Info: " << (debug != NULL ? debug : "none"); g_error_free(error); g_free(debug); break; } -#if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) - case GST_MESSAGE_ELEMENT: { - TizenVideoDecodeAccelerator::Impl* obj_impl = - static_cast(data); - if (obj_impl) { - if (obj_impl->IsXWindowHandleSet()) { -#if GST_VERSION_MAJOR == 1 - if (gst_is_video_overlay_prepare_window_handle_message(msg)) { -#else - if (gst_structure_has_name(msg->structure, "prepare-xid")) { -#endif - obj_impl->OnXWindowIdPrepared(msg); - gst_message_unref(msg); - return GST_BUS_PASS; - } - } - } else { - LOG(ERROR) << __FUNCTION__ << "Accelerator is NULL"; - } - break; - } -#endif default: break; } return GST_BUS_PASS; } - static void StartFeed(GstAppSrc *source, guint size, gpointer app) { + static void StartFeed(GstAppSrc* source, guint size, gpointer app) { DCHECK(source); content::TizenVideoDecodeAccelerator::Impl* impl = static_cast(app); impl->can_feed_ = true; } - static void StopFeed(GstAppSrc *source, gpointer app) { + static void StopFeed(GstAppSrc* source, gpointer app) { DCHECK(source); content::TizenVideoDecodeAccelerator::Impl* impl = static_cast(app); impl->can_feed_ = false; } -#if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) - bool IsXWindowHandleSet() const {return is_x_window_handle_set_;} - void OnXWindowIdPrepared(GstMessage* message); - void SetXWindowHandle(bool handle_set); - void SetPixmap(const int32& gst_width, const int32& gst_height); - void DeregisterDamageHandler(); - static Eina_Bool OnSurfaceChanged(void* ptr_acc, int type, void* event); - static void OnSinkCapChanged( - GstPad* sink_pad, GParamSpec* gparamspec, void* user_data); -#endif - volatile bool can_feed_; volatile bool is_destroying_; GstElement* pipeline_; @@ -226,20 +160,8 @@ struct TizenVideoDecodeAccelerator::Impl { scoped_ptr > io_client_weak_factory_; base::Thread gst_thread_; int bitstream_buffer_id_; -#if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) - scoped_refptr pixmap_surface_; - int pixmap_id_; - gint gst_width_; - gint gst_height_; - Ecore_X_Damage damage_; - Ecore_Event_Handler* damage_handler_; - bool is_x_window_handle_set_; - typedef std::map > PixmapSurfaceTizenMap; - PixmapSurfaceTizenMap xpixmap_buffer_map_; -#else int caps_width_; int caps_height_; -#endif }; TizenVideoDecodeAccelerator::TizenVideoDecodeAccelerator() @@ -253,20 +175,11 @@ bool TizenVideoDecodeAccelerator::Initialize( media::VideoCodecProfile profile, Client* client) { GError* error = NULL; - GstCaps* video_caps = NULL; GstElement* gst_decoder = NULL; + GstElement* gst_parser = NULL; GstBus* gst_bus = NULL; -#if defined(OS_TIZEN) GstPad* video_sink_pad = NULL; - GstElement* gst_parser = NULL; -#if !defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) - GstElement* video_filter_ = NULL; - GstElement* gst_converter = NULL; -#endif -#endif scoped_ptr gst_pipeline; - static GstAppSrcCallbacks appsrc_callbacks = - {&Impl::StartFeed, &Impl::StopFeed, NULL}; CHECK(impl_ == NULL); impl_ = new Impl(); impl_->io_client_weak_factory_.reset( @@ -285,7 +198,7 @@ bool TizenVideoDecodeAccelerator::Initialize( }; if (!gst_is_initialized() && !gst_init_check(NULL, NULL, &error)) { - LOG(ERROR) << __FUNCTION__ << "cannot initialize gstreamer."; + LOG(ERROR) << "Cannot initialize gstreamer."; g_error_free(error); return false; } @@ -293,22 +206,17 @@ bool TizenVideoDecodeAccelerator::Initialize( // pipeline initialization. gst_pipeline.reset(gst_pipeline_new("h264_decode")); if (!gst_pipeline) { - LOG(ERROR) << __FUNCTION__ << "cannot initialize gst pipeline."; + LOG(ERROR) << "Cannot initialize gst pipeline."; return false; } if (!(gst_bus = gst_pipeline_get_bus(GST_PIPELINE(gst_pipeline.get())))) { return false; } -#if GST_VERSION_MAJOR == 1 gst_bus_set_sync_handler(gst_bus, Impl::OnBusMessage, impl_, NULL); -#else - gst_bus_set_sync_handler(gst_bus, Impl::OnBusMessage, impl_); -#endif gst_object_unref(gst_bus); // appsrc initialization. - if (!(impl_->appsrc_ = gst_element_factory_make("appsrc", "src"))) { - LOG(ERROR) << __FUNCTION__ << "cannot initialize gst appsrc."; + if (!impl_->CreateAppSrcElement()) { return false; } if (!gst_bin_add(GST_BIN(gst_pipeline.get()), impl_->appsrc_)) { @@ -316,86 +224,36 @@ bool TizenVideoDecodeAccelerator::Initialize( impl_->appsrc_ = NULL; return false; } - gst_app_src_set_max_bytes(GST_APP_SRC(impl_->appsrc_), INPUT_BUFFER_SIZE); - gst_app_src_set_callbacks(GST_APP_SRC(impl_->appsrc_), &appsrc_callbacks, - static_cast(impl_), NULL); - g_object_set(G_OBJECT(impl_->appsrc_), - "is-live", TRUE, - "block", FALSE, - "min-percent", 80, // if buffer below 80%, need-data emits. - "stream-type", GST_APP_STREAM_TYPE_STREAM, - NULL); - if (!(video_caps = gst_caps_from_string("video/x-h264,framerate=30/1"))) { - return false; - } - gst_app_src_set_caps(GST_APP_SRC(impl_->appsrc_), video_caps); - gst_caps_unref(video_caps); -#if defined(OS_TIZEN) DVLOG(1) << "######################################"; - DVLOG(1) << " USING omx_h264dec DECODER " << (unsigned int)this; + DVLOG(1) << "USING " << kDecoderGstElement <<" DECODER "; DVLOG(1) << "######################################"; - // parser initialization - if (!(gst_parser = gst_element_factory_make("h264parse", "h264parse"))) { - LOG(ERROR) << " cannot create h264parse."; - return false; - } - if(!gst_bin_add(GST_BIN(gst_pipeline.get()), gst_parser)) { - LOG(ERROR) << " cannot add h264parse into decoder pipeline."; - gst_object_unref(gst_parser); - return false; - } - // decoder initialization. - if (!(gst_decoder = gst_element_factory_make(kDecoderGstElement, kDecoderName))) { - LOG(ERROR) << " cannot create " << kDecoderGstElement << "."; + if (!(gst_decoder = gst_element_factory_make(kDecoderGstElement, + kDecoderName))) { + LOG(ERROR) << "Cannot create " << kDecoderGstElement << "."; return false; } if (!gst_bin_add(GST_BIN(gst_pipeline.get()), gst_decoder)) { - LOG(ERROR) << " cannot add " << kDecoderGstElement << " to pipeline."; + LOG(ERROR) << "Cannot add " << kDecoderGstElement << " to pipeline."; gst_object_unref(gst_decoder); return false; } -#if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) - // sink initialization. - if (!(impl_->sink_ = gst_element_factory_make("xvimagesink", "xvimagesink"))) { - LOG(ERROR) << __FUNCTION__ << " cannot create xvimagesink."; - return false; - } - if (!gst_bin_add(GST_BIN(gst_pipeline.get()), impl_->sink_)) { - gst_object_unref(impl_->sink_); - impl_->sink_ = NULL; - return false; - } - g_object_set(impl_->sink_, "rotate", 0, NULL); - if (!(video_sink_pad = gst_element_get_static_pad(impl_->sink_, "sink"))) { + // parser initialization + if (!(gst_parser = gst_element_factory_make(kParserElement, "h264parse"))) { + LOG(ERROR) << "Cannot create " << kParserElement; return false; } - g_signal_connect(video_sink_pad, "notify::caps", - G_CALLBACK(impl_->OnSinkCapChanged), - impl_); - impl_->SetXWindowHandle(false); - gst_object_unref(video_sink_pad); - - // linking the elements. - if (!gst_element_link(impl_->appsrc_, gst_parser)) { - LOG(ERROR) << " Source and gst_parser could not be linked"; + if (!gst_bin_add(GST_BIN(gst_pipeline.get()), gst_parser)) { + LOG(ERROR) << "Cannot add " << kParserElement << " into decoder pipeline."; + gst_object_unref(gst_parser); return false; } - if (!gst_element_link(gst_parser, gst_decoder)) { - LOG(ERROR) << " gst_parser and Decoder could not be linked"; - return false; - } - if (!gst_element_link(gst_decoder, impl_->sink_)) { - LOG(ERROR) << __FUNCTION__ << " Decoder and Sink could not be linked"; - return false; - } -#else - impl_->CreateAppSinkElement(); - if (!impl_->sink_) { + // appsink initialization + if (!impl_->CreateAppSinkElement()) { LOG(ERROR) << "Could not create and add appsink element"; return false; } @@ -404,27 +262,32 @@ bool TizenVideoDecodeAccelerator::Initialize( impl_->sink_ = NULL; return false; } - if (!(gst_converter = gst_element_factory_make("fimcconvert", "cvt"))) { - LOG(ERROR) << __FUNCTION__ << " cannot create fimcconvert."; + +#if defined(TIZEN_MULTIMEDIA_USE_HW_CODEC) + GstElement* video_filter = NULL; + GstElement* gst_converter = NULL; + if (!(gst_converter = gst_element_factory_make(kVideoConvertElement, + kVideoConvertElement))) { + LOG(ERROR) << "Cannot create "<< kVideoConvertElement; return false; } - if(!gst_bin_add(GST_BIN(gst_pipeline.get()), gst_converter)) { - LOG(ERROR) << __FUNCTION__ << " cannot add fimcconvert into pipeline."; + if (!gst_bin_add(GST_BIN(gst_pipeline.get()), gst_converter)) { + LOG(ERROR) << "Cannot add " << kVideoConvertElement << " into pipeline."; gst_object_unref(gst_converter); return false; } - if (!(video_filter_ = gst_element_factory_make("capsfilter", "VideoFilter"))) { - LOG(ERROR) << __FUNCTION__ << " cannot create capsfilter."; + if (!(video_filter = gst_element_factory_make(kCapsFilterElement, + kCapsFilterElement))) { + LOG(ERROR) << "Cannot create " << kCapsFilterElement; return false; } - if(!gst_bin_add(GST_BIN(gst_pipeline.get()), video_filter_)) { - LOG(ERROR) << __FUNCTION__ << " cannot add videoFilter into pipeline."; - gst_object_unref(video_filter_); + if (!gst_bin_add(GST_BIN(gst_pipeline.get()), video_filter)) { + LOG(ERROR) << "Cannot add " << kCapsFilterElement << " into pipeline."; + gst_object_unref(video_filter); return false; } +#endif - // FIXME: SONAL - // OnSinkCapChanged callback is not coming for Appsink implementation if (!(video_sink_pad = gst_element_get_static_pad(impl_->sink_, "sink"))) { LOG(ERROR) << "Could not create video sink pad"; @@ -432,79 +295,40 @@ bool TizenVideoDecodeAccelerator::Initialize( } g_signal_connect( video_sink_pad, "notify::caps", - G_CALLBACK(&Impl::OnSinkCapChanged), impl_); + G_CALLBACK(&Impl::OnSinkCapsChanged), impl_); gst_object_unref(video_sink_pad); - if (!gst_element_link_many(impl_->appsrc_, - gst_parser, - gst_decoder, - gst_converter, - video_filter_, - impl_->sink_, - NULL)) { - LOG(ERROR) << __FUNCTION__ << " cannot link some elements in decode pipeline"; - return false; - } - g_object_set(G_OBJECT(video_filter_), - "caps", - gst_caps_new_simple("video/x-raw","format", G_TYPE_STRING, "I420",NULL), - NULL); -#endif -#else - DVLOG(1) << "######################################"; - DVLOG(1) << " USING ffdec_h264 DECODER"; - DVLOG(1) << "######################################"; - GstElement* gst_colorspace = NULL; - // decoder initialization - if (!(gst_decoder = gst_element_factory_make("ffdec_h264", "H264-decoder"))) { - LOG(ERROR) << __FUNCTION__ << " cannot create ffdec_h264."; - return false; - } - if (!gst_bin_add(GST_BIN(gst_pipeline.get()), gst_decoder)) { - gst_object_unref(gst_decoder); - return false; - } - - // colorspace initialization - if (!(gst_colorspace = gst_element_factory_make("ffmpegcolorspace", "cs"))) { - LOG(ERROR) << __FUNCTION__ << " cannot create ffmpegcolorspace."; - return false; - } - if (!gst_bin_add(GST_BIN(gst_pipeline.get()), gst_colorspace)) { - gst_object_unref(gst_colorspace); - return false; - } - - if (!(impl_->sink_ = gst_element_factory_make("autovideosink", "sink"))) { - LOG(ERROR) << __FUNCTION__ << " cannot create autovideosink."; - return false; - } - if (!gst_bin_add(GST_BIN(gst_pipeline.get()), impl_->sink_)) { - gst_object_unref(impl_->sink_); - impl_->sink_ = NULL; + if (!gst_element_link_many(impl_->appsrc_, gst_parser, gst_decoder, +#if defined(TIZEN_MULTIMEDIA_USE_HW_CODEC) + gst_converter, video_filter, +#endif + impl_->sink_, NULL)) { + LOG(ERROR) << "Cannot link some elements in decode pipeline"; return false; } - if(!gst_element_link_many(impl_->appsrc_, gst_decoder, gst_colorspace, - impl_->sink_, NULL)) { - LOG(ERROR) << __FUNCTION__ << " Some element could not be linked"; - return false; - } +#if defined(USE_OMX_DECODER) + g_object_set(G_OBJECT(video_filter), "caps", + gst_caps_new_simple("video/x-raw", + "format", G_TYPE_STRING, "I420", + NULL), NULL); #endif + if (!impl_->gst_thread_.Start()) { - LOG(ERROR) << __FUNCTION__ << " gst_thread_ failed to start"; + LOG(ERROR) << "gst_thread_ failed to start"; return false; } + GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(gst_pipeline.get()), + GST_DEBUG_GRAPH_SHOW_ALL, + "decoder_graph.dot"); + + impl_->pipeline_ = gst_pipeline.release(); + impl_->gst_thread_.message_loop()->PostTask( FROM_HERE, base::Bind(&TizenVideoDecodeAccelerator::StartDecoder, base::Unretained(this))); - - GST_DEBUG_BIN_TO_DOT_FILE( - GST_BIN(gst_pipeline.get()), GST_DEBUG_GRAPH_SHOW_ALL, "decoder_graph.dot"); - - impl_->pipeline_ = gst_pipeline.release(); return true; } @@ -515,7 +339,7 @@ void TizenVideoDecodeAccelerator::Decode( new base::SharedMemory(bitstream_buffer.handle(), true)); if (!shm->Map(bitstream_buffer.size())) { - LOG(ERROR) << __FUNCTION__ << " could not map bitstream_buffer"; + LOG(ERROR) << "Could not map bitstream_buffer"; NotifyError(media::VideoDecodeAccelerator::UNREADABLE_INPUT); return; } @@ -538,8 +362,7 @@ void TizenVideoDecodeAccelerator::Decode( base::Unretained(this), base::Passed(&buffer_ref))); } else { - DVLOG(2) << __FUNCTION__ - << " Frame drop on decoder:" + DVLOG(2) << "Frame drop on decoder:" << " INPUT Q is FULL"; } } @@ -564,19 +387,18 @@ void TizenVideoDecodeAccelerator::Reset() { void TizenVideoDecodeAccelerator::Destroy() { if (impl_ != NULL) { -#if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) - impl_->SetXWindowHandle(false); - impl_->DeregisterDamageHandler(); - impl_->xpixmap_buffer_map_.clear(); -#endif if (impl_->gst_thread_.IsRunning()) { impl_->gst_thread_.Stop(); } - gst_app_src_end_of_stream(GST_APP_SRC(impl_->appsrc_)); + + if (impl_->appsrc_) + gst_app_src_end_of_stream(GST_APP_SRC(impl_->appsrc_)); + impl_->is_destroying_ = true; if (impl_->pipeline_) { gst_element_set_state(impl_->pipeline_, GST_STATE_NULL); gst_object_unref(GST_OBJECT(impl_->pipeline_)); + impl_->pipeline_ = NULL; } delete impl_; impl_ = NULL; @@ -592,337 +414,162 @@ void TizenVideoDecodeAccelerator::StartDecoder() { gst_element_set_state(impl_->pipeline_, GST_STATE_PLAYING); }; -#if !defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) -void TizenVideoDecodeAccelerator::Impl::OnSinkCapChanged( +void TizenVideoDecodeAccelerator::Impl::OnSinkCapsChanged( GstPad* sink_pad, GParamSpec* gparamspec, void* user_data) { content::TizenVideoDecodeAccelerator::Impl* impl = - static_cast(user_data); - int width = 0, height = 0; -#if GST_VERSION_MAJOR == 1 + static_cast(user_data); GstCaps* caps = gst_pad_get_current_caps(GST_PAD(sink_pad)); - if (caps) { - GstVideoInfo info; - gst_video_info_init(&info); - if (gst_video_info_from_caps(&info, caps)) { - if ((impl->caps_width_ != width) || (impl->caps_height_ != height)) { - impl->caps_width_ = info.width; - impl->caps_height_ = info.height; - } - } - } -#else - if (gst_video_get_size(sink_pad, &width, &height)) { - if ((impl->caps_width_ != width) || (impl->caps_height_ != height)) { - impl->caps_width_ = width; - impl->caps_height_ = height; - } + if (!caps) + return; + GstVideoInfo info; + gst_video_info_init(&info); + if (gst_video_info_from_caps(&info, caps)) { + impl->caps_width_ = info.width; + impl->caps_height_ = info.height; } -#endif + gst_caps_unref(caps); } GstFlowReturn TizenVideoDecodeAccelerator::Impl::OnDecoded( GstAppSink* sink, gpointer app_data) { - GstBuffer* gst_output_buf = NULL; content::TizenVideoDecodeAccelerator::Impl* self = static_cast(app_data); - // FIXME: SONAL - // Once OnSinkCapChanged callback startes coming dont find height - // and width for all buffers, move this code under if block -#if GST_VERSION_MAJOR == 1 GstSample* sample = gst_app_sink_pull_sample(GST_APP_SINK(sink)); - gst_output_buf = gst_sample_get_buffer(sample); - GstMapInfo map; - if (!gst_buffer_map(gst_output_buf, &map, GST_MAP_READ)) - LOG (ERROR) << "Decoded Buffer contains invalid or no info!"; - GstCaps* caps = gst_sample_get_caps(sample); -#else - gst_output_buf = gst_app_sink_pull_buffer(GST_APP_SINK(sink)); - GstCaps* caps = gst_buffer_get_caps(GST_BUFFER(gst_output_buf)); -#endif + if (!sample) { + LOG(ERROR) << "DECODING FRAME FAILED : frame_id " + << self->bitstream_buffer_id_; + return GST_FLOW_ERROR; + } + // FIXME: SONAL + // OnSinkCapsChanged callback is not called for Appsink on Tizen, + // This is an alternate approach to get sample info. +#if !defined(OS_TIZEN) if (!self->caps_width_ || !self->caps_height_) { - if (!caps) { - LOG(ERROR) << __FUNCTION__ << "Could not fetch caps from buffer"; - gst_buffer_unref(gst_output_buf); + const GstStructure* str = gst_sample_get_info(sample); + if (!str || + !gst_structure_get_int(str, "width", &self->caps_width_) || + !gst_structure_get_int(str, "height", &self->caps_height_)) { + LOG(ERROR) << "Buffer information could not be obtained"; + gst_sample_unref(sample); return GST_FLOW_ERROR; - } else { - // No need to unref |GstStructure| - const GstStructure* str = gst_caps_get_structure(caps, 0); - if (!str) { - gst_buffer_unref(gst_output_buf); - gst_caps_unref(caps); - return GST_FLOW_ERROR; - } - if (!gst_structure_get_int(str, "width", &self->caps_width_) || - !gst_structure_get_int(str, "height", &self->caps_height_)) { - LOG(ERROR) << "Buffer information could not be obtained"; - gst_buffer_unref(gst_output_buf); - gst_caps_unref(caps); - return GST_FLOW_ERROR; - } - gst_caps_unref(caps); } } - - if (gst_output_buf) { -#if GST_VERSION_MAJOR == 1 - if (map.data) { -#else - if (gst_output_buf->data) { -#endif - gfx::Rect frame_size = - gfx::Rect(self->caps_width_, self->caps_height_); - self->gst_thread_.message_loop()->PostTask( - FROM_HERE, - base::Bind(&TizenVideoDecodeAccelerator::Impl::DeliverVideoFrame, - base::Unretained(self), - gst_output_buf, - self->bitstream_buffer_id_, - frame_size)); - self->bitstream_buffer_id_ = (self->bitstream_buffer_id_ + 1) & ID_LAST; - } - } else { - gst_buffer_unref(gst_output_buf); -#if GST_VERSION_MAJOR == 1 - gst_sample_unref(sample); -#endif - LOG(ERROR) << __FUNCTION__ - << " DECODING FRAME FAILED : frame_id" - << self->bitstream_buffer_id_; - } -#if GST_VERSION_MAJOR == 1 - gst_buffer_unmap(gst_output_buf, &map); #endif + gfx::Rect frame_size = + gfx::Rect(self->caps_width_, self->caps_height_); + self->gst_thread_.message_loop()->PostTask( + FROM_HERE, + base::Bind(&TizenVideoDecodeAccelerator::Impl::DeliverVideoFrame, + base::Unretained(self), + sample, frame_size)); return GST_FLOW_OK; } +bool TizenVideoDecodeAccelerator::Impl::CreateAppSrcElement() { + if (!(appsrc_ = gst_element_factory_make("appsrc", "src"))) { + LOG(ERROR) << "Cannot initialize gst appsrc."; + return false; + } + static GstAppSrcCallbacks appsrc_callbacks = + {&Impl::StartFeed, &Impl::StopFeed, NULL}; + gst_app_src_set_max_bytes(GST_APP_SRC(appsrc_), INPUT_BUFFER_SIZE); + gst_app_src_set_callbacks(GST_APP_SRC(appsrc_), &appsrc_callbacks, + static_cast(this), NULL); + g_object_set(G_OBJECT(appsrc_), + "is-live", TRUE, + "block", FALSE, + "min-percent", 80, // if buffer below 80%, need-data emits. + "stream-type", GST_APP_STREAM_TYPE_STREAM, + NULL); + GstCaps* video_caps = gst_caps_from_string("video/x-h264,framerate=30/1"); + if (!video_caps) { + gst_object_unref(appsrc_); + return false; + } + gst_app_src_set_caps(GST_APP_SRC(appsrc_), video_caps); + gst_caps_unref(video_caps); + return true; +} -void TizenVideoDecodeAccelerator::Impl::CreateAppSinkElement() { - GstAppSinkCallbacks appsink_callbacks = - { NULL, NULL, &OnDecoded }; - +bool TizenVideoDecodeAccelerator::Impl::CreateAppSinkElement() { if (!(sink_ = gst_element_factory_make("appsink", "sink"))) { - LOG(ERROR) << __FUNCTION__ << "Appsink could not be created"; - return; + LOG(ERROR) << "Appsink could not be created"; + return false; } + + GstAppSinkCallbacks appsink_callbacks = {NULL, NULL, &OnDecoded, NULL}; gst_app_sink_set_callbacks(GST_APP_SINK(sink_), &appsink_callbacks, static_cast(this), NULL); gst_app_sink_set_max_buffers(GST_APP_SINK(sink_), 1); + return true; } void TizenVideoDecodeAccelerator::Impl::DeliverVideoFrame( - GstBuffer* buffer, - int32 bitstream_buffer_id, - gfx::Rect frame_size) { + GstSample* sample, gfx::Rect frame_size) { base::SharedMemory shared_memory; base::SharedMemoryHandle shared_memory_handle; -#if GST_VERSION_MAJOR == 1 + GstBuffer* buffer = gst_sample_get_buffer(sample); GstMapInfo map; - if (!gst_buffer_map(buffer, &map, GST_MAP_READ)) { - LOG (ERROR) << "Encoded Buffer contains invalid or no info.!"; - return; + if (!buffer || !gst_buffer_map(buffer, &map, GST_MAP_READ)) { + LOG(ERROR) << "No Decoded Buffer or contains invalid info!"; + gst_sample_unref(sample); + return; } - uint32 buffer_size = map.size; -#else - uint32 buffer_size = buffer->size; -#endif - if (!shared_memory.CreateAndMapAnonymous(buffer_size)) { - LOG (ERROR) << "Shared Memory creation failed."; + + if (!map.data || !(map.size > 0) || + !shared_memory.CreateAndMapAnonymous(map.size)) { + LOG(ERROR) << "Shared Memory creation failed."; } else { if (!shared_memory.ShareToProcess(base::GetCurrentProcessHandle(), &shared_memory_handle)) { - LOG(ERROR) << __FUNCTION__ << "Could not get handle of Shared Memory"; + LOG(ERROR) << "Could not get handle of Shared Memory"; } else { - memcpy(shared_memory.memory(), -#if GST_VERSION_MAJOR == 1 - map.data, -#else - GST_BUFFER_DATA(buffer), -#endif - buffer_size); + memcpy(shared_memory.memory(), map.data, map.size); io_message_loop_proxy_->PostTask( FROM_HERE, base::Bind(&media::VideoDecodeAccelerator::Client::NotifyDecodeDone, - io_client_weak_factory_->GetWeakPtr(), - shared_memory_handle, - bitstream_buffer_id_, - buffer_size, - frame_size)); + io_client_weak_factory_->GetWeakPtr(), + shared_memory_handle, + bitstream_buffer_id_, + map.size, + frame_size)); + bitstream_buffer_id_ = (bitstream_buffer_id_ + 1) & ID_LAST; } } -#if GST_VERSION_MAJOR == 1 gst_buffer_unmap(buffer, &map); -#endif - gst_buffer_unref(buffer); -} -#endif - -#if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) -void TizenVideoDecodeAccelerator::Impl::OnXWindowIdPrepared( - GstMessage* message) { -#if GST_VERSION_MAJOR == 1 - const GstStructure* structure = gst_message_get_structure(message); - gst_structure_get_int(structure, "video-width", &gst_width_); - gst_structure_get_int(structure, "video-height", &gst_height_); -#else - gst_structure_get_int(message->structure, "video-width", &gst_width_); - gst_structure_get_int(message->structure, "video-height", &gst_height_); -#endif - SetPixmap(gst_width_, gst_height_); - SetXWindowHandle(true); -} - -void TizenVideoDecodeAccelerator::Impl::SetXWindowHandle( - bool handle_set) { - is_x_window_handle_set_ = handle_set; -} - -void TizenVideoDecodeAccelerator::Impl::SetPixmap( - const int32& gst_width, const int32& gst_height) { - int32 key_wh = ConvertWidthAndHeightToKey(gst_width, gst_height); - PixmapSurfaceTizenMap::iterator it = xpixmap_buffer_map_.find(key_wh); - if (it != xpixmap_buffer_map_.end()) { - pixmap_surface_ = it->second; - pixmap_id_ = pixmap_surface_->GetId(); - } else { - pixmap_surface_ = - gfx::EflPixmap::Create(gfx::EflPixmapBase::UsageType::SURFACE, - gfx::Size(gst_width, gst_height)); - if (pixmap_surface_.get() == NULL) { - LOG(ERROR) << __FUNCTION__ << "Failed to create pixmap Surface"; - return; - } - pixmap_id_ = pixmap_surface_->GetId(); - xpixmap_buffer_map_[key_wh] = pixmap_surface_; - } - gst_width_ = gst_width; - gst_height_ = gst_height; - DeregisterDamageHandler(); - - // Register to get notification from ecore for damage updates. - damage_ = ecore_x_damage_new(pixmap_id_, - ECORE_X_DAMAGE_REPORT_RAW_RECTANGLES); - damage_handler_ = ecore_event_handler_add(ECORE_X_EVENT_DAMAGE_NOTIFY, - OnSurfaceChanged, - this); -#if GST_VERSION_MAJOR == 1 - gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(sink_), pixmap_id_); -#else - gst_x_overlay_set_window_handle(GST_X_OVERLAY(sink_), pixmap_id_); -#endif -} - -void TizenVideoDecodeAccelerator::Impl::DeregisterDamageHandler() { - if (damage_) { - ecore_x_damage_free(damage_); - damage_ = 0; - } - if (damage_handler_) { - ecore_event_handler_del(damage_handler_); - damage_handler_ = NULL; - } -} - -// Callback received when pixmap surface is changed/damaged -Eina_Bool TizenVideoDecodeAccelerator::Impl::OnSurfaceChanged(void* ptr_acc, - int type, - void* event) { - TizenVideoDecodeAccelerator::Impl* self = - static_cast(ptr_acc); - - if (self) { - media::Picture picture(self->pixmap_id_, - self->bitstream_buffer_id_, - gfx::Rect(self->gst_width_, self->gst_height_)); - - self->io_message_loop_proxy_->PostTask( - FROM_HERE, - base::Bind(&media::VideoDecodeAccelerator::Client::PictureReady, - self->io_client_weak_factory_->GetWeakPtr(), - picture) ); - self->bitstream_buffer_id_ = (self->bitstream_buffer_id_ + 1) & ID_LAST; - } else { - LOG(ERROR) << __FUNCTION__ << "Accelerator is NULL"; - return ECORE_CALLBACK_CANCEL; - } - return ECORE_CALLBACK_PASS_ON; -} - -void TizenVideoDecodeAccelerator::Impl::OnSinkCapChanged( - GstPad* sink_pad, GParamSpec* gparamspec,void* user_data) { - TizenVideoDecodeAccelerator::Impl* self = - static_cast(user_data); - if (!self) { - LOG(ERROR) << __FUNCTION__ << "Accelerator is NULL"; - return; - } - - int width = 0, height = 0; -#if GST_VERSION_MAJOR == 1 - GstCaps* caps = gst_pad_get_current_caps(GST_PAD(sink_pad)); - if (caps) { - GstVideoInfo info; - gst_video_info_init(&info); - - if (gst_video_info_from_caps(&info, caps)) { - width = info.width; - height = info.height; - if ((self->gst_width_ != width) || (self->gst_height_ != height)) { - self->SetPixmap(width, height); - } - } - } -#else - if (gst_video_get_size(sink_pad, &width, &height)) { - if ((self->gst_width_ != width) || (self->gst_height_ != height)) { - self->SetPixmap(width, height); - } - } -#endif + gst_sample_unref(sample); } -#endif void TizenVideoDecodeAccelerator::OnDecode( scoped_ptr buffer_ref) { if (!buffer_ref) { return; } -#if GST_VERSION_MAJOR == 1 buffer_ref->gst_buffer_ = - gst_buffer_new_wrapped_full(GST_MEMORY_FLAG_READONLY, - static_cast(buffer_ref->shm_->memory()), - buffer_ref->size_, - 0, - buffer_ref->size_, - reinterpret_cast(buffer_ref.get()), - BitstreamBufferRef::Destruct); + gst_buffer_new_wrapped_full( + GST_MEMORY_FLAG_READONLY, + static_cast(buffer_ref->shm_->memory()), + buffer_ref->size_, + 0, + buffer_ref->size_, + reinterpret_cast(buffer_ref.get()), + BitstreamBufferRef::Destruct); if (!buffer_ref->gst_buffer_ || !GST_IS_BUFFER(buffer_ref->gst_buffer_)) { LOG(ERROR) << " gst_buffer_new_wrapped_full failed to allocate memory.!"; return; } -#else - if (!(buffer_ref->gst_buffer_ = gst_buffer_new())) { - return; - } - - GST_BUFFER_MALLOCDATA(buffer_ref->gst_buffer_) = - reinterpret_cast(buffer_ref.get()); - GST_BUFFER_FREE_FUNC(buffer_ref->gst_buffer_) = BitstreamBufferRef::Destruct; - GST_BUFFER_SIZE(buffer_ref->gst_buffer_) = buffer_ref->size_; - GST_BUFFER_DATA(buffer_ref->gst_buffer_) = - static_cast(buffer_ref->shm_->memory()); -#endif if (GST_FLOW_OK != gst_app_src_push_buffer(GST_APP_SRC(impl_->appsrc_), buffer_ref->gst_buffer_)) { - LOG(ERROR) << __FUNCTION__ << " fail to push buffer into decoder pipeline"; + LOG(ERROR) << " fail to push buffer into decoder pipeline"; return; } // lifecycle of buffer_ref will be handled by gstreamer. - (void)buffer_ref.release(); + buffer_ref.release(); } void TizenVideoDecodeAccelerator::NotifyError( diff --git a/tizen_src/chromium_impl/content/common/gpu/media/efl/tizen_video_decode_accelerator.h b/tizen_src/chromium_impl/content/common/gpu/media/efl/tizen_video_decode_accelerator.h index c312e5e..7afea4d 100644 --- a/tizen_src/chromium_impl/content/common/gpu/media/efl/tizen_video_decode_accelerator.h +++ b/tizen_src/chromium_impl/content/common/gpu/media/efl/tizen_video_decode_accelerator.h @@ -2,15 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_COMMON_GPU_MEDIA_TIZEN_VIDEO_DECODE_ACCELERATOR_H_ -#define CONTENT_COMMON_GPU_MEDIA_TIZEN_VIDEO_DECODE_ACCELERATOR_H_ - -#include -#include -#include -#include -#include -#include +#ifndef CONTENT_COMMON_GPU_MEDIA_EFL_TIZEN_VIDEO_DECODE_ACCELERATOR_H_ +#define CONTENT_COMMON_GPU_MEDIA_EFL_TIZEN_VIDEO_DECODE_ACCELERATOR_H_ #include "base/synchronization/lock.h" #include "base/threading/thread.h" @@ -50,4 +43,4 @@ class CONTENT_EXPORT TizenVideoDecodeAccelerator } // namespace content -#endif // CONTENT_COMMON_GPU_MEDIA_TIZEN_VIDEO_DECODE_ACCELERATOR_H_ +#endif // CONTENT_COMMON_GPU_MEDIA_EFL_TIZEN_VIDEO_DECODE_ACCELERATOR_H_ diff --git a/tizen_src/chromium_impl/content/common/gpu/media/efl/tizen_video_encode_accelerator.cc b/tizen_src/chromium_impl/content/common/gpu/media/efl/tizen_video_encode_accelerator.cc index cd76329..305d55e 100644 --- a/tizen_src/chromium_impl/content/common/gpu/media/efl/tizen_video_encode_accelerator.cc +++ b/tizen_src/chromium_impl/content/common/gpu/media/efl/tizen_video_encode_accelerator.cc @@ -22,13 +22,6 @@ using media::VideoFrame; namespace content { -struct GstBufferDeleter { - inline void operator()(GstBuffer* ptr) const { - DCHECK(ptr != NULL); - gst_buffer_unref(ptr); - } -}; - struct GstElementDeleter { inline void operator()(GstElement* ptr) const { DCHECK(ptr != NULL); @@ -43,22 +36,22 @@ enum { INPUT_BUFFER_COUNT = 5, // default input buffer counts of omx_h264enc MAX_BUFFERING = 60, MAX_FRAME_RATE = 30, - // Max bitrate in bps - MAX_BITRATE = 2000000, - MAX_OUTPUT_BUFFERS = 30 // Maximum queue size of output buffers + MAX_BITRATE = 2000000, // Max bitrate in bps + MAX_OUTPUT_BUFFERS = 30, // Maximum queue size of output buffers + MAX_WIDTH = 1280, + MAX_HEIGHT = 720, }; + // Gstreamer elements and names. const char* kEncoderName = "encoder"; -const char* kConvertorName = "cvt"; -#if GST_VERSION_MAJOR == 1 +#if defined(OS_TIZEN) const char* kEncoderGstElement = "omxh264enc"; -const char* kConvertorGstElement = "fimcconvert"; +const char* kBitrateProperty = "target-bitrate"; #else -const char* kEncoderGstElement = "omx_h264enc"; -const char* kConvertorGstElement = "c2dconvert"; +const char* kEncoderGstElement = "x264enc"; +const char* kBitrateProperty = "bitrate"; #endif - media::VideoEncodeAccelerator* CreateTizenVideoEncodeAccelerator() { return new TizenVideoEncodeAccelerator(); } @@ -100,8 +93,9 @@ struct TizenVideoEncodeAccelerator::OutputBuffer { key_frame_(key_frame) {} virtual ~OutputBuffer() { - if(buffer_) - gst_buffer_unref(buffer_); + if (buffer_) + gst_buffer_unref(buffer_); + buffer_ = NULL; } GstBuffer* buffer_; @@ -114,7 +108,7 @@ struct TizenVideoEncodeAccelerator::Impl { : pipeline_(NULL), encoder_(NULL), appsrc_(NULL), - gst_thread_("GSTEncoder"), + gst_thread_("TizenEncoderThreadGst"), enable_framedrop_(false), io_client_weak_factory_(client), child_message_loop_proxy_(msg_loop), @@ -124,6 +118,7 @@ struct TizenVideoEncodeAccelerator::Impl { can_feed_(false) {} void DeliverVideoFrame(); + bool CreateAppSrcElement(); static GstFlowReturn OnEncoded(GstAppSink *sink,gpointer data); static void StartFeed(GstAppSrc *source, guint size, gpointer data); static void StopFeed(GstAppSrc *source, gpointer data); @@ -150,36 +145,27 @@ struct TizenVideoEncodeAccelerator::Impl { void TizenVideoEncodeAccelerator::Impl::DeliverVideoFrame() { media::BitstreamBuffer* bs_buffer = NULL; - GstBuffer* buffer = NULL; bool key_frame = false; - gsize gst_buffer_size = 0; -#if GST_VERSION_MAJOR == 1 GstMapInfo map; -#endif - scoped_ptr shm; + scoped_ptr out_buffer = NULL; - if(output_buffers_.empty()) + if (output_buffers_.empty()) return; if (encoder_output_queue_.empty()) { // Observed till now that output_buffers_ size does not exceed 4-5. // Therefore this code will be called in very rare situations. - if(output_buffers_.size() >= MAX_OUTPUT_BUFFERS) { + if (output_buffers_.size() >= MAX_OUTPUT_BUFFERS) { enable_framedrop_ = true; - TizenVideoEncodeAccelerator::OutputBuffer* drop_buffer = NULL; - { - base::AutoLock auto_lock(output_queue_lock_); - while(!output_buffers_.empty()) { - drop_buffer = output_buffers_.front(); - if (drop_buffer->key_frame_) - break; - output_buffers_.pop(); - gst_buffer_unref(drop_buffer->buffer_); - delete drop_buffer; - } + base::AutoLock auto_lock(output_queue_lock_); + while (!output_buffers_.empty()) { + out_buffer.reset(output_buffers_.front()); + if (out_buffer->key_frame_) + break; + output_buffers_.pop(); + out_buffer.reset(NULL); } - return; } return; } @@ -193,89 +179,109 @@ void TizenVideoEncodeAccelerator::Impl::DeliverVideoFrame() { LOG(ERROR) << "Failed to map SHM"; io_client_weak_factory_.GetWeakPtr()->NotifyError( media::VideoEncodeAccelerator::kPlatformFailureError); - gst_buffer_unref(buffer); + return; } - { base::AutoLock auto_lock(output_queue_lock_); - buffer = output_buffers_.front()->buffer_; + out_buffer.reset(output_buffers_.front()); output_buffers_.pop(); } -#if GST_VERSION_MAJOR == 1 - if (!gst_buffer_map(buffer, &map, GST_MAP_READ)) { - LOG (ERROR) << "Encoded Buffer contains invalid or no info.!"; - return; - } - gst_buffer_size = map.size; -#else - gst_buffer_size = buffer->size; -#endif + if (!gst_buffer_map(out_buffer->buffer_, &map, GST_MAP_READ)) { + LOG(ERROR) << "Encoded Buffer contains invalid or no info.!"; + return; + } - if (gst_buffer_size > shm->mapped_size()) { + if (!map.data && map.size > shm->mapped_size()) { LOG(ERROR) << "Encoded buff too large: " - << gst_buffer_size << ">" << shm->mapped_size(); + << map.size << ">" << shm->mapped_size(); io_client_weak_factory_.GetWeakPtr()->NotifyError( media::VideoEncodeAccelerator::kPlatformFailureError); - gst_buffer_unref(buffer); + } else { + //copying data to shared memory. + memcpy(static_cast(shm->memory()), map.data, map.size); + child_message_loop_proxy_->PostTask( + FROM_HERE, + base::Bind(&media::VideoEncodeAccelerator::Client::BitstreamBufferReady, + io_client_weak_factory_.GetWeakPtr(), + bs_buffer->id(), + map.size, + key_frame)); } - //copying data to shared memory. -#if GST_VERSION_MAJOR == 1 - memcpy(static_cast(shm->memory()), map.data, gst_buffer_size); - gst_buffer_unmap(buffer, &map); -#else - memcpy(static_cast(shm->memory()), buffer->data, gst_buffer_size); -#endif + gst_buffer_unmap(out_buffer->buffer_, &map); +} - child_message_loop_proxy_->PostTask( - FROM_HERE, - base::Bind(&media::VideoEncodeAccelerator::Client::BitstreamBufferReady, - io_client_weak_factory_.GetWeakPtr(), - bs_buffer->id(), - gst_buffer_size, - key_frame)); +bool TizenVideoEncodeAccelerator::Impl::CreateAppSrcElement() { + if (!(appsrc_ = gst_element_factory_make ("appsrc", "src"))) { + LOG(ERROR) << "Cannot initialize gst appsrc."; + return false; + } + GstCaps* appsrc_caps = gst_caps_new_simple( + "video/x-raw", + "format", G_TYPE_STRING, "I420", + "width", G_TYPE_INT, view_size_.width(), + "height", G_TYPE_INT, view_size_.height(), + "framerate", GST_TYPE_FRACTION, 30, 1, + "rotate", G_TYPE_INT, 0, + NULL); + GstAppSrcCallbacks appsrc_callbacks = + { &TizenVideoEncodeAccelerator::Impl::StartFeed, + &TizenVideoEncodeAccelerator::Impl::StopFeed, + NULL }; + + guint64 max_input_buffer = + INPUT_BUFFER_COUNT * VideoFrame::AllocationSize(VideoFrame::I420, + view_size_); + gst_app_src_set_callbacks(GST_APP_SRC(appsrc_), &appsrc_callbacks, + static_cast(this), NULL); + gst_app_src_set_max_bytes(GST_APP_SRC(appsrc_), max_input_buffer); + gst_app_src_set_caps(GST_APP_SRC(appsrc_), appsrc_caps); + + g_object_set(G_OBJECT(appsrc_), + "is-live", TRUE, + "block", FALSE, + "do-timestamp", TRUE, + "min-latency", (gint64)(0), + "max-latency", (gint64)(0), + "min-percent", 80, // if buffer below 80%, need-data emits. + "stream-type", GST_APP_STREAM_TYPE_STREAM, + "format", GST_FORMAT_DEFAULT, + NULL); + gst_caps_unref(appsrc_caps); + return true; } GstFlowReturn TizenVideoEncodeAccelerator::Impl::OnEncoded( GstAppSink *sink, gpointer data) { - bool key_frame = false; - GstBuffer* gst_output_buf = NULL; TizenVideoEncodeAccelerator::Impl* impl = static_cast(data); -#if GST_VERSION_MAJOR == 1 - gst_output_buf = gst_sample_get_buffer(gst_app_sink_pull_sample(GST_APP_SINK(sink))); + + GstSample* sample = gst_app_sink_pull_sample(GST_APP_SINK(sink)); + GstBuffer* buffer = gst_sample_get_buffer(sample); GstMapInfo map; - if (!gst_buffer_map(gst_output_buf, &map, GST_MAP_READ)) - LOG (ERROR) << "Encoded Buffer contains invalid or no info!"; -#else - gst_output_buf = gst_app_sink_pull_buffer(GST_APP_SINK(sink)); -#endif + if (!buffer || !gst_buffer_map(buffer, &map, GST_MAP_READ)) { + LOG(ERROR) << "Encoded Buffer contains invalid or no info!"; + gst_sample_unref(sample); + return GST_FLOW_ERROR; + } - if (gst_output_buf) { - if (!GST_BUFFER_FLAG_IS_SET(gst_output_buf, GST_BUFFER_FLAG_DELTA_UNIT)) { + if (map.data) { + bool key_frame = false; + if (!GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT)) { key_frame = true; } -#if GST_VERSION_MAJOR == 1 - if (map.data) { -#else - if (gst_output_buf->data) { -#endif - base::AutoLock auto_lock(impl->output_queue_lock_); - impl->output_buffers_.push( - new TizenVideoEncodeAccelerator::OutputBuffer(gst_output_buf, - key_frame)); - } - } else { - LOG(ERROR) << __FUNCTION__ << " ENCODING FRAME FAILED"; + base::AutoLock auto_lock(impl->output_queue_lock_); + impl->output_buffers_.push( + new TizenVideoEncodeAccelerator::OutputBuffer(gst_buffer_ref(buffer), + key_frame)); } -#if GST_VERSION_MAJOR == 1 - gst_buffer_unmap(gst_output_buf, &map); -#endif + gst_buffer_unmap(buffer, &map); + gst_sample_unref(sample); return GST_FLOW_OK; } void TizenVideoEncodeAccelerator::Impl::StartFeed( - GstAppSrc *source, guint size, gpointer data) { + GstAppSrc* source, guint size, gpointer data) { TizenVideoEncodeAccelerator::Impl* impl = static_cast(data); DCHECK(impl); @@ -283,7 +289,7 @@ void TizenVideoEncodeAccelerator::Impl::StartFeed( } void TizenVideoEncodeAccelerator::Impl::StopFeed( - GstAppSrc *source, gpointer data) { + GstAppSrc* source, gpointer data) { TizenVideoEncodeAccelerator::Impl* impl = static_cast(data); DCHECK(impl); @@ -300,8 +306,8 @@ TizenVideoEncodeAccelerator::GetSupportedProfiles() { std::vector profiles; media::VideoEncodeAccelerator::SupportedProfile profile; profile.profile = media::H264PROFILE_BASELINE; - profile.max_resolution.SetSize(1280, 720); - profile.max_framerate_numerator = 30; + profile.max_resolution.SetSize(MAX_WIDTH, MAX_HEIGHT); + profile.max_framerate_numerator = MAX_FRAME_RATE; profile.max_framerate_denominator = 1; profiles.push_back(profile); @@ -314,8 +320,7 @@ bool TizenVideoEncodeAccelerator::Initialize( media::VideoCodecProfile output_profile, uint32 initial_bitrate, Client* client) { - DVLOG(1) << __FUNCTION__ - << " size :" << input_visible_size.ToString() + DVLOG(1) << " size :" << input_visible_size.ToString() << " max bitrate :" << MAX_BITRATE << "bps"; DCHECK(impl_ == NULL); if (media::H264PROFILE_MIN > output_profile || @@ -337,11 +342,12 @@ bool TizenVideoEncodeAccelerator::Initialize( base::MessageLoop::current()->PostTask( FROM_HERE, - base::Bind(&media::VideoEncodeAccelerator::Client::RequireBitstreamBuffers, - impl_->io_client_weak_factory_.GetWeakPtr(), - (unsigned int)INPUT_BUFFER_COUNT, - input_visible_size, - MAX_BITRATE / 8)); // Maximum bytes for a frame by MAX_BITRATE. + base::Bind( + &media::VideoEncodeAccelerator::Client::RequireBitstreamBuffers, + impl_->io_client_weak_factory_.GetWeakPtr(), + (unsigned int)INPUT_BUFFER_COUNT, + input_visible_size, + MAX_BITRATE / 8)); // Maximum bytes for a frame by MAX_BITRATE. return true; } @@ -350,8 +356,7 @@ void TizenVideoEncodeAccelerator::Encode( bool force_keyframe) { size_t frame_size = VideoFrame::AllocationSize(VideoFrame::I420, frame->coded_size()); - DVLOG(3) << __FUNCTION__ - << " coded_size :" << frame->coded_size().ToString() + DVLOG(3) << " coded_size :" << frame->coded_size().ToString() << " natural_size :" << frame->natural_size().ToString(); scoped_ptr buffer_ref; @@ -363,7 +368,7 @@ void TizenVideoEncodeAccelerator::Encode( frame_size)); if (!buffer_ref) { - LOG(ERROR) << __FUNCTION__ << "malloc failed"; + LOG(ERROR) << "malloc failed"; return; } @@ -375,7 +380,7 @@ void TizenVideoEncodeAccelerator::Encode( base::Passed(&buffer_ref), force_keyframe)); } else { - DVLOG(2) << __FUNCTION__ << " [WEBRTC] . FRAME DROP :" + DVLOG(2) << " [WEBRTC] . FRAME DROP :" << " can_feed_:" << impl_->can_feed_ << " is_destroying_:" << impl_->is_destroying_; } @@ -392,35 +397,27 @@ void TizenVideoEncodeAccelerator::UseOutputBitstreamBuffer( void TizenVideoEncodeAccelerator::RequestEncodingParametersChange( uint32 bitrate, uint32 framerate) { - DVLOG(2) << __FUNCTION__ - << " bitrate: " << bitrate + DVLOG(2) << " bitrate: " << bitrate << " framerate: " << framerate; if (bitrate > 0 && bitrate != impl_->gst_bitrate_) { impl_->gst_bitrate_ = bitrate; // Omx Encoder expects bitrate in bps whereas ffenc expects bitrate in kbps // Information can be gained by gst-inspect -#if defined(OS_TIZEN) g_object_set(G_OBJECT(impl_->encoder_), -#if GST_VERSION_MAJOR == 1 - "target-bitrate", -#else - "bitrate", -#endif + kBitrateProperty, +#if defined(OS_TIZEN) std::min(bitrate, static_cast(MAX_BITRATE)), - NULL); #else - g_object_set(G_OBJECT(impl_->encoder_), - "bitrate", std::min(bitrate, static_cast(MAX_BITRATE)) / 1000, - NULL); #endif + NULL); } } void TizenVideoEncodeAccelerator::Destroy() { if (impl_) { DCHECK(impl_->thread_checker_.CalledOnValidThread()); - if(impl_->appsrc_) + if (impl_->appsrc_) gst_app_src_end_of_stream(GST_APP_SRC(impl_->appsrc_)); { @@ -438,16 +435,18 @@ void TizenVideoEncodeAccelerator::Destroy() { impl_->io_timer_.Stop(); while (!impl_->encoder_output_queue_.empty()) { - media::BitstreamBuffer bitstream_buffer = impl_->encoder_output_queue_.back(); + media::BitstreamBuffer bitstream_buffer = + impl_->encoder_output_queue_.back(); // created shm and let it go out of scope automatically. scoped_ptr shm( new base::SharedMemory(bitstream_buffer.handle(), false)); impl_->encoder_output_queue_.pop_back(); } + scoped_ptr output_buffer = NULL; while (!impl_->output_buffers_.empty()) { - OutputBuffer* output_buffer = impl_->output_buffers_.front(); - gst_buffer_unref(output_buffer->buffer_); + output_buffer.reset(impl_->output_buffers_.front()); impl_->output_buffers_.pop(); + output_buffer.reset(NULL); } delete impl_; } @@ -462,43 +461,23 @@ void TizenVideoEncodeAccelerator::OnEncode( return; } -#if defined(OS_TIZEN) && GST_VERSION_MAJOR != 1 - g_object_set(impl_->encoder_, - "force-i-frame", - (force_keyframe || impl_->enable_framedrop_) ? TRUE : FALSE, - NULL); -#endif - -#if GST_VERSION_MAJOR == 1 bufref->gst_buffer_ = - gst_buffer_new_wrapped_full(GST_MEMORY_FLAG_READONLY, - static_cast(bufref->frame_->data(VideoFrame::kYPlane)), - bufref->size_, - 0, - bufref->size_, - reinterpret_cast(bufref), - BitstreamBufferRef::Destruct); + gst_buffer_new_wrapped_full( + GST_MEMORY_FLAG_READONLY, + static_cast(bufref->frame_->data(VideoFrame::kYPlane)), + bufref->size_, + 0, + bufref->size_, + reinterpret_cast(bufref), + BitstreamBufferRef::Destruct); if (!bufref->gst_buffer_ || !GST_IS_BUFFER(bufref->gst_buffer_)) { - LOG(INFO) << " gst_buffer_new_wrapped_full failed to allocate memory."; + LOG(INFO) << "gst_buffer_new_wrapped_full failed to allocate memory."; return; } -#else - if (!(bufref->gst_buffer_ = gst_buffer_new())) { - LOG(ERROR) << __FUNCTION__ << " gst_buffer_new failed to allocate memory.!"; - return; - } - - GST_BUFFER_MALLOCDATA(bufref->gst_buffer_) = reinterpret_cast(bufref); - GST_BUFFER_FREE_FUNC(bufref->gst_buffer_) = BitstreamBufferRef::Destruct; - GST_BUFFER_SIZE(bufref->gst_buffer_) = bufref->size_; - GST_BUFFER_DATA(bufref->gst_buffer_) = - static_cast(bufref->frame_->data(VideoFrame::kYPlane)); -#endif if (GST_FLOW_OK != gst_app_src_push_buffer(GST_APP_SRC(impl_->appsrc_), bufref->gst_buffer_)) { - LOG(ERROR) << __FUNCTION__ - << " error while pushing buffer int appsrc on encoder."; + LOG(ERROR) << "Error while pushing buffer int appsrc on encoder."; gst_buffer_unref(bufref->gst_buffer_); } @@ -509,33 +488,17 @@ void TizenVideoEncodeAccelerator::OnUseOutputBitstreamBuffer( const media::BitstreamBuffer& buffer) { impl_->encoder_output_queue_.push_back(buffer); - DVLOG(2) << __FUNCTION__ - << " output buffer is ready to use: " << buffer.id() + DVLOG(2) << " output buffer is ready to use: " << buffer.id() << " out queue size: " << impl_->encoder_output_queue_.size(); } bool TizenVideoEncodeAccelerator::StartEncoder() { GError* error = NULL; - GstCaps* appsrc_caps = NULL; GstElement* gst_appsink = NULL; scoped_ptr gst_pipeline; - guint64 max_input_buffer = - INPUT_BUFFER_COUNT * VideoFrame::AllocationSize(VideoFrame::I420, - impl_->view_size_); - GstAppSrcCallbacks appsrc_callbacks = - { &TizenVideoEncodeAccelerator::Impl::StartFeed, - &TizenVideoEncodeAccelerator::Impl::StopFeed, - NULL }; - GstAppSinkCallbacks appsink_callbacks = - { NULL, NULL, &TizenVideoEncodeAccelerator::Impl::OnEncoded }; - - if (impl_->pipeline_ != NULL) { - return false; - } - if (!gst_is_initialized() && !gst_init_check(NULL, NULL, &error)) { - LOG(ERROR) << __FUNCTION__ << " cannot initialize gstreamer."; + LOG(ERROR) << "Cannot initialize gstreamer."; g_error_free(error); return false; } @@ -543,122 +506,74 @@ bool TizenVideoEncodeAccelerator::StartEncoder() { // pipeline initialization gst_pipeline.reset(gst_pipeline_new("h264_encode")); if (!gst_pipeline) { - LOG(ERROR) << __FUNCTION__ << " cannot initialize gst pipeline."; + LOG(ERROR) << "Cannot initialize gst pipeline."; return false; } - // appsrc initialization - if (!(impl_->appsrc_ = gst_element_factory_make ("appsrc", "src"))) { - LOG(ERROR) << __FUNCTION__ << "cannot initialize gst appsrc."; + if (!impl_->CreateAppSrcElement()) { return false; } + if (!gst_bin_add(GST_BIN(gst_pipeline.get()), impl_->appsrc_)) { - LOG(ERROR) << __FUNCTION__ << " cannot add gst appsrc into encoder pipeline."; + LOG(ERROR) << "Cannot add gst appsrc to encoder pipeline."; gst_object_unref(impl_->appsrc_); impl_->appsrc_ = NULL; return false; } - appsrc_caps = gst_caps_new_simple( -#if GST_VERSION_MAJOR == 1 - "video/x-raw", - "format", G_TYPE_STRING, gst_video_format_to_string(GST_VIDEO_FORMAT_I420), -#else - "video/x-raw-yuv", - "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC('I', '4', '2', '0'), -#endif - "width", G_TYPE_INT, impl_->view_size_.width(), - "height", G_TYPE_INT, impl_->view_size_.height(), - "framerate", GST_TYPE_FRACTION, 30, 1, - "rotate", G_TYPE_INT, 0, - NULL); - if (!appsrc_caps) { - LOG(ERROR) << __FUNCTION__ << " cannot create appsrc caps"; - return false; - } - gst_app_src_set_callbacks(GST_APP_SRC(impl_->appsrc_), &appsrc_callbacks, - static_cast(impl_), NULL); - gst_app_src_set_max_bytes(GST_APP_SRC(impl_->appsrc_), max_input_buffer); - gst_app_src_set_caps(GST_APP_SRC(impl_->appsrc_), appsrc_caps); // appsink initialization if (!(gst_appsink = gst_element_factory_make("appsink", "sink"))) { - LOG(ERROR) << "cannot create appsink for encoder pipeline."; + LOG(ERROR) << "Cannot create appsink for encoder pipeline."; return false; } if (!gst_bin_add(GST_BIN(gst_pipeline.get()), gst_appsink)) { - LOG(ERROR) << "cannot add gst appsink into encoder pipeline."; + LOG(ERROR) << "Cannot add gst appsink into encoder pipeline."; gst_object_unref(gst_appsink); return false; } + + GstAppSinkCallbacks appsink_callbacks = + { NULL, NULL, &TizenVideoEncodeAccelerator::Impl::OnEncoded, NULL }; gst_app_sink_set_callbacks(GST_APP_SINK(gst_appsink), &appsink_callbacks, static_cast(impl_), NULL); gst_app_sink_set_max_buffers(GST_APP_SINK(gst_appsink), 1); -#ifdef OS_TIZEN DVLOG(1) << "######################################"; - DVLOG(1) << " USING omx_h264enc ENCODER"; + DVLOG(1) << "USING " << kEncoderGstElement << " ENCODER"; DVLOG(1) << "######################################"; // encoder initialization - if (!(impl_->encoder_ = gst_element_factory_make(kEncoderGstElement, kEncoderName))) { - LOG(ERROR) << __FUNCTION__ << " cannot create " << kEncoderGstElement << "."; + if (!(impl_->encoder_ = gst_element_factory_make(kEncoderGstElement, + kEncoderName))) { + LOG(ERROR) << "Cannot create " << kEncoderGstElement << "."; return false; } - if(!gst_bin_add(GST_BIN(gst_pipeline.get()), impl_->encoder_)) { - LOG(ERROR) << __FUNCTION__ << " cannot add omx_h264enc into encoder pipeline."; + if (!gst_bin_add(GST_BIN(gst_pipeline.get()), impl_->encoder_)) { + LOG(ERROR) << "Cannot add " + << kEncoderGstElement << "into encoder pipeline."; gst_object_unref(impl_->encoder_); impl_->encoder_ = NULL; return false; } + +#if defined(OS_TIZEN) g_object_set(impl_->encoder_, "control-rate", 2, // 1:VBR_CFR 2:CBR_CFR 3:VBR_VFR 4:CBR_VFR -#if GST_VERSION_MAJOR == 1 - "target-bitrate", impl_->gst_bitrate_, -#else - "encoder-profile", 1, // BASELINE_PROFILE - "byte-stream", TRUE, - "bitrate", impl_->gst_bitrate_, -#endif - NULL); - - g_object_set(G_OBJECT(impl_->appsrc_), - "is-live", TRUE, - "block", FALSE, - "do-timestamp", TRUE, - "min-latency", (gint64)(0), - "max-latency", (gint64)(0), - "min-percent", 80, // if buffer below 80%, need-data emits. - "stream-type", GST_APP_STREAM_TYPE_STREAM, - "format", GST_FORMAT_DEFAULT, + kBitrateProperty, impl_->gst_bitrate_, NULL); - - g_object_set(gst_appsink, "sync", FALSE, NULL); - - if (!gst_element_link(impl_->appsrc_, impl_->encoder_)) { - LOG(ERROR) << " cannot link impl_->appsrc_ with encoder_."; - return false; - } - - if (!gst_element_link(impl_->encoder_, gst_appsink)) { - LOG(ERROR) << " cannot link encoder_ to sink."; - return false; - } #else - DVLOG(1) << "######################################"; - DVLOG(1) << " USING x264enc ENCODER"; - DVLOG(1) << "######################################"; - GstElement* gst_parser = NULL; - // parser initialization + GstElement* gst_parser = NULL; if (!(gst_parser = gst_element_factory_make("videoparse", "parse"))) { - LOG(ERROR) << __FUNCTION__ << " cannot create videoparse."; + LOG(ERROR) << "Cannot create videoparse."; return false; } - if(!gst_bin_add(GST_BIN(gst_pipeline.get()), gst_parser)) { - LOG(ERROR) << __FUNCTION__ << " cannot add videoparse into encoder pipeline."; + if (!gst_bin_add(GST_BIN(gst_pipeline.get()), gst_parser)) { + LOG(ERROR) << "Cannot add videoparse to encoder pipeline."; gst_object_unref(gst_parser); return false; } + g_object_set(gst_parser, "format", GST_VIDEO_FORMAT_I420, "width", impl_->view_size_.width(), @@ -666,50 +581,37 @@ bool TizenVideoEncodeAccelerator::StartEncoder() { "framerate", INITIAL_FRAMERATE, 1, NULL); - if (!(impl_->encoder_ = gst_element_factory_make ("x264enc","encoder"))) { - LOG(ERROR) << __FUNCTION__ << " cannot create x264enc encoder."; - return false; - } - if(!gst_bin_add(GST_BIN(gst_pipeline.get()), impl_->encoder_)) { - LOG(ERROR) << __FUNCTION__ << " cannot add x264enc into encoder pipeline."; - gst_object_unref(impl_->encoder_); - return false; - } g_object_set(impl_->encoder_, "byte-stream", TRUE, - "bitrate", impl_->gst_bitrate_, - "tune",0x00000004,"profile", 1, NULL); - - g_object_set(G_OBJECT(impl_->appsrc_), - "is-live", TRUE, - "block", FALSE, - "do-timestamp", TRUE, - "stream-type", 0, - "min-latency", (gint64)(0), - "max-latency", (gint64)(0), - "format", GST_FORMAT_TIME, - NULL); + kBitrateProperty, impl_->gst_bitrate_ / 1000, // to kbit/s + "tune", 0x00000004, NULL); +#endif g_object_set(gst_appsink, "sync", FALSE, NULL); - if (!gst_element_link_many(impl_->appsrc_, gst_parser, + if (!gst_element_link_many(impl_->appsrc_, +#if !defined(OS_TIZEN) + gst_parser, +#endif impl_->encoder_, gst_appsink, NULL)) { - LOG(ERROR) << __FUNCTION__ << " cannot link for encoder pipeline."; + LOG(ERROR) << "Cannot link for encoder pipeline."; return false; } -#endif if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(gst_pipeline.get(), GST_STATE_PLAYING)) { - LOG(ERROR) << __FUNCTION__ << " cannot start encoder pipeline."; + LOG(ERROR) << "Cannot start encoder pipeline."; return false; } + impl_->io_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(10), impl_, &TizenVideoEncodeAccelerator::Impl::DeliverVideoFrame); - GST_DEBUG_BIN_TO_DOT_FILE( - GST_BIN(gst_pipeline.get()), GST_DEBUG_GRAPH_SHOW_ALL, "encoder_graph.dot"); + + GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(gst_pipeline.get()), + GST_DEBUG_GRAPH_SHOW_ALL, + "encoder_graph.dot"); impl_->pipeline_ = gst_pipeline.release(); return true; diff --git a/tizen_src/chromium_impl/content/common/gpu/media/efl/tizen_video_encode_accelerator.h b/tizen_src/chromium_impl/content/common/gpu/media/efl/tizen_video_encode_accelerator.h index 0821880..a43a892 100644 --- a/tizen_src/chromium_impl/content/common/gpu/media/efl/tizen_video_encode_accelerator.h +++ b/tizen_src/chromium_impl/content/common/gpu/media/efl/tizen_video_encode_accelerator.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_COMMON_GPU_MEDIA_TIZEN_VIDEO_ENCODE_ACCELERATOR_H_ -#define CONTENT_COMMON_GPU_MEDIA_TIZEN_VIDEO_ENCODE_ACCELERATOR_H_ +#ifndef CONTENT_COMMON_GPU_MEDIA_EFL_TIZEN_VIDEO_ENCODE_ACCELERATOR_H_ +#define CONTENT_COMMON_GPU_MEDIA_EFL_TIZEN_VIDEO_ENCODE_ACCELERATOR_H_ #include "base/threading/thread.h" #include "base/synchronization/lock.h" @@ -49,4 +49,4 @@ class CONTENT_EXPORT TizenVideoEncodeAccelerator } // namespace content -#endif // CONTENT_COMMON_GPU_MEDIA_TIZEN_VIDEO_ENCODE_ACCELERATOR_TIZEN_H_ +#endif // CONTENT_COMMON_GPU_MEDIA_EFL_TIZEN_VIDEO_ENCODE_ACCELERATOR_TIZEN_H_ diff --git a/tizen_src/chromium_impl/content/common/media/efl/media_player_messages_efl.h b/tizen_src/chromium_impl/content/common/media/efl/media_player_messages_efl.h index 02fc757..28ecd29 100644 --- a/tizen_src/chromium_impl/content/common/media/efl/media_player_messages_efl.h +++ b/tizen_src/chromium_impl/content/common/media/efl/media_player_messages_efl.h @@ -2,19 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// IPC messages for tizen media player. +// IPC messages for efl media player. // Multiply-included message file, hence no include guard. #include "content/common/content_export.h" +#include "content/common/media/efl/media_player_messages_enums_efl.h" #include "ipc/ipc_message_macros.h" -#include "media/base/media_keys.h" #include "media/base/efl/demuxer_stream_player_params_efl.h" #include "media/base/efl/media_player_manager_efl.h" -#include "ui/gfx/rect_f.h" +#include "media/base/media_keys.h" +#include "ui/gfx/geometry/rect_f.h" #undef IPC_MESSAGE_EXPORT #define IPC_MESSAGE_EXPORT CONTENT_EXPORT -#define IPC_MESSAGE_START MediaPlayerEflMsgStart +#define IPC_MESSAGE_START MediaPlayerMsgStart IPC_ENUM_TRAITS(media::AudioCodec) IPC_ENUM_TRAITS(media::MediaPlayerEfl::ReadyState) @@ -58,8 +59,8 @@ IPC_STRUCT_TRAITS_BEGIN(media::MediaPlayerEfl::TimeRanges) IPC_STRUCT_TRAITS_MEMBER(end) IPC_STRUCT_TRAITS_END() -// Initialize Gst player. -IPC_MESSAGE_ROUTED5(MediaPlayerGstHostMsg_Init, +// Initialize Efl player. +IPC_MESSAGE_ROUTED5(MediaPlayerEflHostMsg_Init, int /* player_id */, MediaPlayerHostMsg_Initialize_Type /* type */, GURL /* URL */, @@ -67,68 +68,63 @@ IPC_MESSAGE_ROUTED5(MediaPlayerGstHostMsg_Init, int /* demuxer client id */) // Deinitialize Gst player. -IPC_MESSAGE_ROUTED1(MediaPlayerGstHostMsg_DeInit, +IPC_MESSAGE_ROUTED1(MediaPlayerEflHostMsg_DeInit, int /* player_id */) // Start playback. -IPC_MESSAGE_ROUTED1(MediaPlayerGstHostMsg_Play, +IPC_MESSAGE_ROUTED1(MediaPlayerEflHostMsg_Play, int /* player_id */) // Pause playback. -IPC_MESSAGE_ROUTED1(MediaPlayerGstHostMsg_Pause, +IPC_MESSAGE_ROUTED1(MediaPlayerEflHostMsg_Pause, int /* player_id */) // Set volume. -IPC_MESSAGE_ROUTED2(MediaPlayerGstHostMsg_SetVolume, +IPC_MESSAGE_ROUTED2(MediaPlayerEflHostMsg_SetVolume, int /* player_id */, double /* volume */) // Set playback rate. -IPC_MESSAGE_ROUTED2(MediaPlayerGstHostMsg_SetRate, +IPC_MESSAGE_ROUTED2(MediaPlayerEflHostMsg_SetRate, int /* player_id */, double /* rate */) // Playback duration. -IPC_MESSAGE_ROUTED2(MediaPlayerGstMsg_DurationChanged, +IPC_MESSAGE_ROUTED2(MediaPlayerEflMsg_DurationChanged, int /* player_id */, double /* time */) // Current duration. -IPC_MESSAGE_ROUTED2(MediaPlayerGstMsg_TimeUpdate, +IPC_MESSAGE_ROUTED2(MediaPlayerEflMsg_TimeUpdate, int /* player_id */, double /* time */) -// Pause state. -IPC_MESSAGE_ROUTED2(MediaPlayerGstMsg_OnPauseStateChange, - int /* player_id */, - bool /* state */) - // Seek state. -IPC_MESSAGE_ROUTED2(MediaPlayerGstMsg_OnSeekStateChange, +IPC_MESSAGE_ROUTED2(MediaPlayerEflMsg_OnSeekStateChange, int /* player_id */, bool /* state */) // Current buffer range. -IPC_MESSAGE_ROUTED2(MediaPlayerGstMsg_BufferUpdate, +IPC_MESSAGE_ROUTED2(MediaPlayerEflMsg_BufferUpdate, int /* player_id */, std::vector /*buffer_range*/) // Playback completed. -IPC_MESSAGE_ROUTED1(MediaPlayerGstMsg_TimeChanged, +IPC_MESSAGE_ROUTED1(MediaPlayerEflMsg_TimeChanged, int /* player_id */) // Ready state change. -IPC_MESSAGE_ROUTED2(MediaPlayerGstMsg_ReadyStateChange, +IPC_MESSAGE_ROUTED2(MediaPlayerEflMsg_ReadyStateChange, int /* player_id */, media::MediaPlayerEfl::ReadyState /* state */) // Network state change. -IPC_MESSAGE_ROUTED2(MediaPlayerGstMsg_NetworkStateChange, +IPC_MESSAGE_ROUTED2(MediaPlayerEflMsg_NetworkStateChange, int /* player_id */, media::MediaPlayerEfl::NetworkState /* state */) // Gst media data has changed. -IPC_MESSAGE_ROUTED5(MediaPlayerGstMsg_MediaDataChanged, +IPC_MESSAGE_ROUTED5(MediaPlayerEflMsg_MediaDataChanged, int /* player_id */, int /* format */, int /* height */, @@ -136,65 +132,56 @@ IPC_MESSAGE_ROUTED5(MediaPlayerGstMsg_MediaDataChanged, int /* media */) // On new frame available. -IPC_MESSAGE_ROUTED4(MediaPlayerGstMsg_NewFrameAvailable, +IPC_MESSAGE_ROUTED4(MediaPlayerEflMsg_NewFrameAvailable, int /* player_id */, base::SharedMemoryHandle /* Handle */, uint32 /* length */, base::TimeDelta /* time stamp */) -#ifdef OS_TIZEN -IPC_MESSAGE_ROUTED3(MediaPlayerGstMsg_PlatformSurfaceUpdated, +#if defined(OS_TIZEN) +IPC_MESSAGE_ROUTED3(MediaPlayerEflMsg_PlatformSurfaceUpdated, int /* player_id */, int /* pixmap_id */, base::TimeDelta /* time stamp */) #endif // Seek. -IPC_MESSAGE_ROUTED2(MediaPlayerGstHostMsg_Seek, +IPC_MESSAGE_ROUTED2(MediaPlayerEflHostMsg_Seek, int /* player_id */, double /* time */) // For MSE internal seek request. -IPC_MESSAGE_ROUTED2(MediaPlayerGstMsg_SeekRequest, +IPC_MESSAGE_ROUTED2(MediaPlayerEflMsg_SeekRequest, int /* player_id */, double /* time_to_seek */) // Sent after the renderer demuxer has seeked. -IPC_MESSAGE_CONTROL2(MediaPlayerGstHostMsg_DemuxerSeekDone, +IPC_MESSAGE_CONTROL2(MediaPlayerEflHostMsg_DemuxerSeekDone, int /* demuxer_client_id */, base::TimeDelta /* actual_browser_seek_time */) // Inform the media source player that the demuxer is ready. -IPC_MESSAGE_CONTROL2(MediaPlayerGstHostMsg_DemuxerReady, +IPC_MESSAGE_CONTROL2(MediaPlayerEflHostMsg_DemuxerReady, int /* demuxer_client_id */, media::DemuxerConfigs /* configs */) // Sent when the data was read from the ChunkDemuxer. -IPC_MESSAGE_CONTROL3(MediaPlayerGstHostMsg_ReadFromDemuxerAck, +IPC_MESSAGE_CONTROL3(MediaPlayerEflHostMsg_ReadFromDemuxerAck, int /* demuxer_client_id */, base::SharedMemoryHandle /* Handle */, media::DemuxedBufferMetaData /* meta data of buffer*/) -// Sent when the data was read from the ChunkDemuxer. -IPC_MESSAGE_CONTROL2(MediaPlayerGstHostMsg_BufferMetaDataAck, - int /* demuxer_client_id */, - media::DemuxedBufferMetaData /* meta data of buffer*/) - // Inform the media source player of changed media duration from demuxer. -IPC_MESSAGE_CONTROL2(MediaPlayerGstHostMsg_DurationChanged, +IPC_MESSAGE_CONTROL2(MediaPlayerEflHostMsg_DurationChanged, int /* demuxer_client_id */, base::TimeDelta /* duration */) -// The player needs new config data -IPC_MESSAGE_CONTROL1(MediaPlayerGstMsg_MediaConfigRequest, - int /* demuxer_client_id */) - // The media source player reads data from demuxer -IPC_MESSAGE_CONTROL2(MediaPlayerGstMsg_ReadFromDemuxer, +IPC_MESSAGE_CONTROL2(MediaPlayerEflMsg_ReadFromDemuxer, int /* demuxer_client_id */, media::DemuxerStream::Type /* type */) // Requests renderer demuxer seek. -IPC_MESSAGE_CONTROL2(MediaPlayerGstMsg_DemuxerSeekRequest, +IPC_MESSAGE_CONTROL2(MediaPlayerEflMsg_DemuxerSeekRequest, int /* demuxer_client_id */, base::TimeDelta /* time_to_seek */) diff --git a/tizen_src/chromium_impl/content/common/message_generator_efl.h b/tizen_src/chromium_impl/content/common/message_generator_efl.h index 5ad3f81..efa516b 100644 --- a/tizen_src/chromium_impl/content/common/message_generator_efl.h +++ b/tizen_src/chromium_impl/content/common/message_generator_efl.h @@ -9,3 +9,7 @@ #if defined(OS_TIZEN_MOBILE) #include "content/common/tts_messages_efl.h" #endif + +#if defined(TIZEN_MULTIMEDIA_SUPPORT) +#include "content/common/media/efl/media_player_messages_efl.h" +#endif diff --git a/tizen_src/chromium_impl/content/renderer/media/efl/audio_decoder_gstreamer.h b/tizen_src/chromium_impl/content/renderer/media/efl/audio_decoder_gstreamer.h index c937ee7..bfd1178 100644 --- a/tizen_src/chromium_impl/content/renderer/media/efl/audio_decoder_gstreamer.h +++ b/tizen_src/chromium_impl/content/renderer/media/efl/audio_decoder_gstreamer.h @@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_RENDERER_MEDIA_TIZEN_AUDIO_DECODER_GSTREAMER_H_ -#define CONTENT_RENDERER_MEDIA_TIZEN_AUDIO_DECODER_GSTREAMER_H_ +#ifndef CONTENT_RENDERER_MEDIA_EFL_AUDIO_DECODER_GSTREAMER_H_ +#define CONTENT_RENDERER_MEDIA_EFL_AUDIO_DECODER_GSTREAMER_H_ #include "content/renderer/media/android/audio_decoder_android.h" -#endif // CONTENT_RENDERER_MEDIA_TIZEN_AUDIO_DECODER_GSTREAMER_H_ \ No newline at end of file +#endif // CONTENT_RENDERER_MEDIA_EFL_AUDIO_DECODER_GSTREAMER_H_ \ No newline at end of file diff --git a/tizen_src/chromium_impl/content/renderer/media/efl/media_source_delegate_efl.cc b/tizen_src/chromium_impl/content/renderer/media/efl/media_source_delegate_efl.cc index aa251f1..359c884 100644 --- a/tizen_src/chromium_impl/content/renderer/media/efl/media_source_delegate_efl.cc +++ b/tizen_src/chromium_impl/content/renderer/media/efl/media_source_delegate_efl.cc @@ -45,10 +45,7 @@ MediaSourceDelegateEfl::MediaSourceDelegateEfl( pending_seek_time_(media::kNoTimestamp()), is_audio_read_fired_(false), is_video_read_fired_(false), - is_demuxer_ready_(false), - shared_memory_size_(0) { - VLOG(1) << "MediaSourceDelegateEfl::" << __FUNCTION__ - << ": Demuxer Client Id = " << demuxer_client_id_; + is_demuxer_ready_(false) { DCHECK(!chunk_demuxer_); } @@ -63,29 +60,39 @@ MediaSourceDelegateEfl::~MediaSourceDelegateEfl() { void MediaSourceDelegateEfl::InitializeMediaSource( const MediaSourceOpenedCB& media_source_opened_cb, - const media::Demuxer::NeedKeyCB& need_key_cb, + const media::Demuxer::EncryptedMediaInitDataCB& emedia_init_data_cb, const media::SetDecryptorReadyCB& set_decryptor_ready_cb, const UpdateNetworkStateCB& update_network_state_cb, const DurationChangeCB& duration_change_cb) { DCHECK(main_loop_->BelongsToCurrentThread()); DCHECK(!media_source_opened_cb.is_null()); media_source_opened_cb_ = media_source_opened_cb; - need_key_cb_ = need_key_cb; + emedia_init_data_cb_ = emedia_init_data_cb; set_decryptor_ready_cb_ = set_decryptor_ready_cb; update_network_state_cb_ = media::BindToCurrentLoop(update_network_state_cb); duration_change_cb_ = duration_change_cb; chunk_demuxer_.reset(new media::ChunkDemuxer( - media::BindToCurrentLoop(base::Bind( - &MediaSourceDelegateEfl::OnDemuxerOpened, main_weak_this_)), - media::BindToCurrentLoop(base::Bind( - &MediaSourceDelegateEfl::OnNeedKey, main_weak_this_)), - base::Bind(&LogMediaSourceError, media_log_), - false)); + media::BindToCurrentLoop( + base::Bind(&MediaSourceDelegateEfl::OnDemuxerOpened, + main_weak_this_)), + media::BindToCurrentLoop( + base::Bind(&MediaSourceDelegateEfl::OnEncryptedMediaInitData, + main_weak_this_)), + base::Bind(&LogMediaSourceError, media_log_), media_log_, false)); media_task_runner_->PostTask(FROM_HERE, base::Bind(&MediaSourceDelegateEfl::InitializeDemuxer, - base::Unretained(this))); + base::Unretained(this))); +} + +void MediaSourceDelegateEfl::AddBufferedTimeRange(base::TimeDelta start, + base::TimeDelta end) { + buffered_time_ranges_.Add(start, end); +} + +blink::WebTimeRanges MediaSourceDelegateEfl::Buffered() const { + return media::ConvertToWebTimeRanges(buffered_time_ranges_); } void MediaSourceDelegateEfl::InitializeDemuxer() { @@ -94,18 +101,18 @@ void MediaSourceDelegateEfl::InitializeDemuxer() { chunk_demuxer_->Initialize( this, base::Bind(&MediaSourceDelegateEfl::OnDemuxerInitDone, - media_weak_factory_.GetWeakPtr()), + media_weak_factory_.GetWeakPtr()), false); } -void MediaSourceDelegateEfl::OnNeedKey( +void MediaSourceDelegateEfl::OnEncryptedMediaInitData ( const std::string& type, const std::vector& init_data) { DCHECK(main_loop_->BelongsToCurrentThread()); - if (need_key_cb_.is_null()) { + if (emedia_init_data_cb_.is_null()) { return; } - need_key_cb_.Run(type, init_data); + emedia_init_data_cb_.Run(type, init_data); } void MediaSourceDelegateEfl::OnDemuxerOpened() { @@ -122,6 +129,22 @@ void MediaSourceDelegateEfl::OnDemuxerError( update_network_state_cb_.Run(PipelineErrorToNetworkState(status)); } +void MediaSourceDelegateEfl::AddTextStream( + media::DemuxerStream* /* text_stream */ , + const media::TextTrackConfig& /* config */ ) { + NOTIMPLEMENTED(); +} + +void MediaSourceDelegateEfl::RemoveTextStream( + media::DemuxerStream* /* text_stream */ ) { + NOTIMPLEMENTED(); +} + +bool MediaSourceDelegateEfl::CanNotifyDemuxerReady() { + DCHECK(media_task_runner_->BelongsToCurrentThread()); + return is_demuxer_ready_; +} + void MediaSourceDelegateEfl::OnDemuxerInitDone( media::PipelineStatus status) { DCHECK(media_task_runner_->BelongsToCurrentThread()); @@ -154,8 +177,9 @@ void MediaSourceDelegateEfl::InitAudioDecryptingDemuxerStream() { audio_decrypting_demuxer_stream_->Initialize( audio_stream_, - base::Bind(&MediaSourceDelegateEfl::OnAudioDecryptingDemuxerStreamInitDone, - media_weak_factory_.GetWeakPtr())); + base::Bind( + &MediaSourceDelegateEfl::OnAudioDecryptingDemuxerStreamInitDone, + media_weak_factory_.GetWeakPtr())); } void MediaSourceDelegateEfl::InitVideoDecryptingDemuxerStream() { @@ -166,8 +190,9 @@ void MediaSourceDelegateEfl::InitVideoDecryptingDemuxerStream() { video_decrypting_demuxer_stream_->Initialize( video_stream_, - base::Bind(&MediaSourceDelegateEfl::OnVideoDecryptingDemuxerStreamInitDone, - media_weak_factory_.GetWeakPtr())); + base::Bind( + &MediaSourceDelegateEfl::OnVideoDecryptingDemuxerStreamInitDone, + media_weak_factory_.GetWeakPtr())); } @@ -210,7 +235,10 @@ void MediaSourceDelegateEfl::OnVideoDecryptingDemuxerStreamInitDone( void MediaSourceDelegateEfl::NotifyDemuxerReady() { DCHECK(media_task_runner_->BelongsToCurrentThread()); DCHECK(is_demuxer_ready_); - + if (!demuxer_client_ || (!audio_stream_ && !video_stream_)) { + OnDemuxerError(media::PIPELINE_ERROR_INITIALIZATION_FAILED); + return; + } scoped_ptr configs(new media::DemuxerConfigs()); if (audio_stream_) { media::AudioDecoderConfig audio_config = @@ -232,9 +260,7 @@ void MediaSourceDelegateEfl::NotifyDemuxerReady() { configs->video_extra_data = std::vector(video_config.extra_data(), video_config.extra_data() + video_config.extra_data_size()); } - if (demuxer_client_) { - demuxer_client_->DemuxerReady(demuxer_client_id_, *configs); - } + demuxer_client_->DemuxerReady(demuxer_client_id_, *configs); } void MediaSourceDelegateEfl::OnReadFromDemuxer( @@ -263,8 +289,6 @@ void MediaSourceDelegateEfl::OnReadFromDemuxer( void MediaSourceDelegateEfl::Stop(const base::Closure& stop_cb) { DCHECK(main_loop_->BelongsToCurrentThread()); - VLOG(1) << "MediaSourceDelegateEfl::" << __FUNCTION__ - << ": Demuxer Client Id = " << demuxer_client_id_; if (!chunk_demuxer_) { DCHECK(!demuxer_client_); @@ -280,7 +304,6 @@ void MediaSourceDelegateEfl::Stop(const base::Closure& stop_cb) { // 1. shutdown demuxer. // 2. On media thread, call stop demuxer. - // 3. On callback, post message and self destory. chunk_demuxer_->Shutdown(); media_task_runner_->PostTask( FROM_HERE, @@ -309,10 +332,6 @@ void MediaSourceDelegateEfl::StopDemuxer(const base::Closure& stop_cb) { stop_cb.Run(); } -void MediaSourceDelegateEfl::OnMediaConfigRequest() { - NotifyDemuxerReady(); -} - void MediaSourceDelegateEfl::SeekInternal( const base::TimeDelta& seek_time) { DCHECK(media_task_runner_->BelongsToCurrentThread()); @@ -325,6 +344,9 @@ void MediaSourceDelegateEfl::OnBufferReady( media::DemuxerStream::Type type, media::DemuxerStream::Status status, const scoped_refptr& buffer) { + uint32 shared_memory_size = -1; + base::SharedMemory shared_memory; + base::SharedMemoryHandle foreign_memory_handle; scoped_ptr meta_data( new media::DemuxedBufferMetaData()); @@ -342,45 +364,38 @@ void MediaSourceDelegateEfl::OnBufferReady( break; case media::DemuxerStream::kConfigChanged: - VLOG(1) << "[RENDER] : DemuxerStream::kConfigChanged"; NotifyDemuxerReady(); break; case media::DemuxerStream::kOk: if (buffer.get()->end_of_stream()) { - VLOG(1) << "[RENDER] : DemuxerStream::kOk but |end_of_stream|"; meta_data->end_of_stream = true; break; } - shared_memory_size_ = buffer.get()->data_size(); - if (!shared_memory_.CreateAndMapAnonymous(shared_memory_size_)) { + shared_memory_size = buffer.get()->data_size(); + if (!shared_memory.CreateAndMapAnonymous(shared_memory_size)) { LOG (ERROR) << "Shared Memory creation failed."; return; } - if (!shared_memory_.ShareToProcess(base::Process::Current().Handle(), - &foreign_memory_handle_)) { + if (!shared_memory.ShareToProcess(base::Process::Current().Handle(), + &foreign_memory_handle)) { LOG (ERROR) << "Shared Memory handle could not be obtained"; - shared_memory_.Close(); return; } - memcpy(shared_memory_.memory(), (void*)buffer.get()->writable_data(), - shared_memory_size_); + memcpy(shared_memory.memory(), (void*)buffer.get()->writable_data(), + shared_memory_size); meta_data->timestamp = buffer.get()->timestamp(); meta_data->time_duration = buffer.get()->duration(); - if (demuxer_client_) { - meta_data->size = shared_memory_size_; - demuxer_client_->ReadFromDemuxerAck( - demuxer_client_id_, foreign_memory_handle_, *meta_data); - } - shared_memory_.Close(); - return; + meta_data->size = shared_memory_size; break; default: NOTREACHED(); } if (demuxer_client_) - demuxer_client_->BufferMetaDataAck(demuxer_client_id_, *meta_data); + demuxer_client_->ReadFromDemuxerAck(demuxer_client_id_, + foreign_memory_handle, + *meta_data); } void MediaSourceDelegateEfl::StartWaitingForSeek( @@ -389,7 +404,8 @@ void MediaSourceDelegateEfl::StartWaitingForSeek( if (!chunk_demuxer_) return; - // Called from |webmediaplayertizen| only. + + // Called from |webmediaplayerefl| only. is_demuxer_seek_done_ = false; seeking_pending_seek_ = false; is_seeking_ = true; @@ -411,7 +427,6 @@ void MediaSourceDelegateEfl::CancelPendingSeek( // // This block will handle when |gstreamer| is seeking and new seek came in // between. - VLOG(1) << "No need to CancelPendingSeek"; is_demuxer_seek_done_ = false; pending_seek_ = false; chunk_demuxer_->StartWaitingForSeek(seek_time); @@ -427,18 +442,16 @@ void MediaSourceDelegateEfl::StartSeek( bool is_seeking_pending_seek) { DCHECK(media_task_runner_->BelongsToCurrentThread()); - VLOG(1)<< "MediaSourceDelegateEfl::" << __FUNCTION__ - << " : " << seek_time.InSecondsF(); if (!chunk_demuxer_) return; + is_seeking_ = true; is_demuxer_seek_done_ = false; if (is_seeking_pending_seek) seeking_pending_seek_ = is_seeking_pending_seek; - else if (seeking_pending_seek_) { - VLOG(1)<< "Ignoring seek request from Efl"; + else if (seeking_pending_seek_) return; - } + seek_time_ = seek_time; SeekInternal(seek_time); } @@ -455,8 +468,6 @@ void MediaSourceDelegateEfl::OnDemuxerSeekDone( StartSeek(pending_seek_time_, true); seek_time_ = pending_seek_time_; } else { - VLOG(1) << "Actual time that Gstreamer seeks : " - << seek_time_.InMilliseconds(); seeking_pending_seek_ = false; is_seeking_ = false; is_demuxer_seek_done_ = true; diff --git a/tizen_src/chromium_impl/content/renderer/media/efl/media_source_delegate_efl.h b/tizen_src/chromium_impl/content/renderer/media/efl/media_source_delegate_efl.h index a388c6b..1bcdc31 100644 --- a/tizen_src/chromium_impl/content/renderer/media/efl/media_source_delegate_efl.h +++ b/tizen_src/chromium_impl/content/renderer/media/efl/media_source_delegate_efl.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_RENDERER_MEDIA_TIZEN_MEDIA_SOURCE_DELEGATE_EFL_H_ -#define CONTENT_RENDERER_MEDIA_TIZEN_MEDIA_SOURCE_DELEGATE_EFL_H_ +#ifndef CONTENT_RENDERER_MEDIA_EFL_MEDIA_SOURCE_DELEGATE_EFL_H_ +#define CONTENT_RENDERER_MEDIA_EFL_MEDIA_SOURCE_DELEGATE_EFL_H_ #include "content/renderer/media/efl/renderer_demuxer_efl.h" #include "media/base/decoder_buffer.h" @@ -17,7 +17,7 @@ namespace content { class MediaSourceDelegateEfl : public media::DemuxerHost { -public: + public: typedef base::Callback MediaSourceOpenedCB; typedef base::Callback @@ -32,33 +32,35 @@ public: ~MediaSourceDelegateEfl(); //DemuxerHost implementation. - virtual void AddBufferedTimeRange( + void AddBufferedTimeRange( base::TimeDelta start, - base::TimeDelta end) override {}; + base::TimeDelta end) override; // Sets the duration of the media in microseconds. // Duration may be kInfiniteDuration() if the duration is not known. - virtual void SetDuration(base::TimeDelta duration) override; + void SetDuration(base::TimeDelta duration) override; // Stops execution of the pipeline due to a fatal error. Do not call this // method with PIPELINE_OK. - virtual void OnDemuxerError(media::PipelineStatus error) override; + void OnDemuxerError(media::PipelineStatus error) override; // Add |text_stream| to the collection managed by the text renderer. - virtual void AddTextStream( + void AddTextStream( media::DemuxerStream* text_stream, - const media::TextTrackConfig& config) override {}; + const media::TextTrackConfig& config) override; // Remove |text_stream| from the presentation. - virtual void RemoveTextStream(media::DemuxerStream* text_stream) override {}; + void RemoveTextStream(media::DemuxerStream* text_stream) override; void InitializeMediaSource( const MediaSourceOpenedCB& media_source_opened_cb, - const media::Demuxer::NeedKeyCB& need_key_cb, + const media::Demuxer::EncryptedMediaInitDataCB& emedia_init_data_cb, const media::SetDecryptorReadyCB& set_decryptor_ready_cb, const UpdateNetworkStateCB& update_network_state_cb, const DurationChangeCB& duration_change_cb); + blink::WebTimeRanges Buffered() const; + // Called when DemuxerStreamPlayer needs to read data from ChunkDemuxer. void OnReadFromDemuxer(media::DemuxerStream::Type type); @@ -78,24 +80,18 @@ public: const base::TimeDelta& seek_time, bool is_seeking_pending_seek); - // Callback for ChunkDemuxer::Seek() and callback chain for resetting - // decrypted audio/video streams if present. - // - // Runs on the media thread. + // Callback for ChunkDemuxer::Seek(). void OnDemuxerSeekDone(media::PipelineStatus status); - // Called when the player needs the new config data from ChunkDemuxer. - void OnMediaConfigRequest(); - private: - void OnNeedKey(const std::string& type, const std::vector& init_data); + void OnEncryptedMediaInitData(const std::string& type, + const std::vector& init_data); void OnDemuxerOpened(); void InitializeDemuxer(); void OnDemuxerInitDone(media::PipelineStatus status); - // Stops and clears objects on the media thread. void StopDemuxer(const base::Closure& stop_cb); - + bool CanNotifyDemuxerReady(); void NotifyDemuxerReady(); void OnDurationChanged(const base::TimeDelta& duration); void OnBufferReady( @@ -136,9 +132,10 @@ public: scoped_ptr chunk_demuxer_; media::DemuxerStream* audio_stream_; media::DemuxerStream* video_stream_; + media::Ranges buffered_time_ranges_; media::SetDecryptorReadyCB set_decryptor_ready_cb_; - media::Demuxer::NeedKeyCB need_key_cb_; + media::Demuxer::EncryptedMediaInitDataCB emedia_init_data_cb_; scoped_ptr audio_decrypting_demuxer_stream_; scoped_ptr video_decrypting_demuxer_stream_; @@ -160,12 +157,8 @@ public: bool is_video_read_fired_; bool is_demuxer_ready_; - - uint32 shared_memory_size_; - base::SharedMemory shared_memory_; - base::SharedMemoryHandle foreign_memory_handle_; }; } // namespace content -#endif // CONTENT_RENDERER_MEDIA_TIZEN_MEDIA_SOURCE_DELEGATE_EFL_H_ +#endif // CONTENT_RENDERER_MEDIA_EFL_MEDIA_SOURCE_DELEGATE_EFL_H_ diff --git a/tizen_src/chromium_impl/content/renderer/media/efl/renderer_demuxer_efl.cc b/tizen_src/chromium_impl/content/renderer/media/efl/renderer_demuxer_efl.cc index 1dcc2c6..ff82fe3 100644 --- a/tizen_src/chromium_impl/content/renderer/media/efl/renderer_demuxer_efl.cc +++ b/tizen_src/chromium_impl/content/renderer/media/efl/renderer_demuxer_efl.cc @@ -14,6 +14,10 @@ namespace content { +scoped_refptr CreateRendererDemuxerEfl() { + return new RendererDemuxerEfl(); +} + RendererDemuxerEfl::RendererDemuxerEfl() : thread_safe_sender_(RenderThreadImpl::current()->thread_safe_sender()), media_task_runner_( @@ -40,9 +44,8 @@ void RendererDemuxerEfl::RemoveDelegate(int demuxer_client_id) { bool RendererDemuxerEfl::OnMessageReceived(const IPC::Message& message) { switch (message.type()) { - case MediaPlayerGstMsg_ReadFromDemuxer::ID: - case MediaPlayerGstMsg_MediaConfigRequest::ID: - case MediaPlayerGstMsg_DemuxerSeekRequest::ID: + case MediaPlayerEflMsg_ReadFromDemuxer::ID: + case MediaPlayerEflMsg_DemuxerSeekRequest::ID: media_task_runner_->PostTask(FROM_HERE, base::Bind( &RendererDemuxerEfl::DispatchMessage, this, message)); return true; @@ -53,7 +56,7 @@ bool RendererDemuxerEfl::OnMessageReceived(const IPC::Message& message) { void RendererDemuxerEfl::DemuxerReady( int demuxer_client_id, const media::DemuxerConfigs& configs) { - thread_safe_sender_->Send(new MediaPlayerGstHostMsg_DemuxerReady( + thread_safe_sender_->Send(new MediaPlayerEflHostMsg_DemuxerReady( demuxer_client_id, configs)); } @@ -61,36 +64,27 @@ void RendererDemuxerEfl::ReadFromDemuxerAck( int demuxer_client_id, base::SharedMemoryHandle foreign_memory_handle, const media::DemuxedBufferMetaData& meta_data) { - thread_safe_sender_->Send(new MediaPlayerGstHostMsg_ReadFromDemuxerAck( + thread_safe_sender_->Send(new MediaPlayerEflHostMsg_ReadFromDemuxerAck( demuxer_client_id, foreign_memory_handle, meta_data)); } -void RendererDemuxerEfl::BufferMetaDataAck( - int demuxer_client_id, - const media::DemuxedBufferMetaData& meta_data) { - thread_safe_sender_->Send(new MediaPlayerGstHostMsg_BufferMetaDataAck( - demuxer_client_id, meta_data)); -} - void RendererDemuxerEfl::DemuxerSeekDone( int demuxer_client_id, const base::TimeDelta& actual_browser_seek_time) { - thread_safe_sender_->Send(new MediaPlayerGstHostMsg_DemuxerSeekDone( + thread_safe_sender_->Send(new MediaPlayerEflHostMsg_DemuxerSeekDone( demuxer_client_id, actual_browser_seek_time)); } void RendererDemuxerEfl::DurationChanged(int demuxer_client_id, const base::TimeDelta& duration) { - thread_safe_sender_->Send(new MediaPlayerGstHostMsg_DurationChanged( + thread_safe_sender_->Send(new MediaPlayerEflHostMsg_DurationChanged( demuxer_client_id, duration)); } void RendererDemuxerEfl::DispatchMessage(const IPC::Message& message) { IPC_BEGIN_MESSAGE_MAP(RendererDemuxerEfl, message) - IPC_MESSAGE_HANDLER(MediaPlayerGstMsg_ReadFromDemuxer, OnReadFromDemuxer) - IPC_MESSAGE_HANDLER(MediaPlayerGstMsg_MediaConfigRequest, - OnMediaConfigRequest) - IPC_MESSAGE_HANDLER(MediaPlayerGstMsg_DemuxerSeekRequest, + IPC_MESSAGE_HANDLER(MediaPlayerEflMsg_ReadFromDemuxer, OnReadFromDemuxer) + IPC_MESSAGE_HANDLER(MediaPlayerEflMsg_DemuxerSeekRequest, OnDemuxerSeekRequest) IPC_END_MESSAGE_MAP() } @@ -111,10 +105,4 @@ void RendererDemuxerEfl::OnDemuxerSeekRequest( delegate->StartSeek(time_to_seek, false); } -void RendererDemuxerEfl::OnMediaConfigRequest(int demuxer_client_id) { - MediaSourceDelegateEfl* delegate = delegates_.Lookup(demuxer_client_id); - if (delegate) - delegate->OnMediaConfigRequest(); -} - } // namespace content diff --git a/tizen_src/chromium_impl/content/renderer/media/efl/renderer_demuxer_efl.h b/tizen_src/chromium_impl/content/renderer/media/efl/renderer_demuxer_efl.h index 21b0444..2ca0ab5 100644 --- a/tizen_src/chromium_impl/content/renderer/media/efl/renderer_demuxer_efl.h +++ b/tizen_src/chromium_impl/content/renderer/media/efl/renderer_demuxer_efl.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_RENDERER_MEDIA_TIZEN_RENDERER_DEMUXER_EFL_H_ -#define CONTENT_RENDERER_MEDIA_TIZEN_RENDERER_DEMUXER_EFL_H_ +#ifndef CONTENT_RENDERER_MEDIA_EFL_RENDERER_DEMUXER_EFL_H_ +#define CONTENT_RENDERER_MEDIA_EFL_RENDERER_DEMUXER_EFL_H_ #include "base/atomic_sequence_num.h" #include "base/id_map.h" @@ -46,7 +46,7 @@ class RendererDemuxerEfl : public IPC::MessageFilter { void RemoveDelegate(int demuxer_client_id); // IPC::ChannelProxy::MessageFilter overrides. - virtual bool OnMessageReceived(const IPC::Message& message) override; + bool OnMessageReceived(const IPC::Message& message) override; // media::DemuxerEflClient "implementation". void DemuxerReady( @@ -56,9 +56,6 @@ class RendererDemuxerEfl : public IPC::MessageFilter { int demuxer_client_id, base::SharedMemoryHandle foreign_memory_handle, const media::DemuxedBufferMetaData& meta_data); - void BufferMetaDataAck( - int demuxer_client_id, - const media::DemuxedBufferMetaData& meta_data); void DemuxerSeekDone( int demuxer_client_id, const base::TimeDelta& actual_browser_seek_time); @@ -66,7 +63,7 @@ class RendererDemuxerEfl : public IPC::MessageFilter { protected: friend class base::RefCountedThreadSafe; - virtual ~RendererDemuxerEfl(); + ~RendererDemuxerEfl() override; private: void DispatchMessage(const IPC::Message& message); @@ -74,7 +71,6 @@ class RendererDemuxerEfl : public IPC::MessageFilter { media::DemuxerStream::Type type); void OnDemuxerSeekRequest(int demuxer_client_id, const base::TimeDelta& time_to_seek); - void OnMediaConfigRequest(int demuxer_client_id); base::AtomicSequenceNumber next_demuxer_client_id_; @@ -87,4 +83,4 @@ class RendererDemuxerEfl : public IPC::MessageFilter { } // namespace content -#endif // CONTENT_RENDERER_MEDIA_TIZEN_RENDERER_DEMUXER_EFL_H_ +#endif // CONTENT_RENDERER_MEDIA_EFL_RENDERER_DEMUXER_EFL_H_ diff --git a/tizen_src/chromium_impl/content/renderer/media/efl/renderer_media_player_manager_efl.cc b/tizen_src/chromium_impl/content/renderer/media/efl/renderer_media_player_manager_efl.cc index a56c248..1bb7a6b 100644 --- a/tizen_src/chromium_impl/content/renderer/media/efl/renderer_media_player_manager_efl.cc +++ b/tizen_src/chromium_impl/content/renderer/media/efl/renderer_media_player_manager_efl.cc @@ -7,54 +7,55 @@ #include "base/bind.h" #include "base/message_loop/message_loop.h" #include "content/common/media/efl/media_player_messages_efl.h" -#include "ui/gfx/rect_f.h" namespace content { -RendererMediaPlayerManagerEfl::RendererMediaPlayerManagerEfl( +RendererMediaPlayerManager* CreateRendererMediaPlayerManager( + RenderFrame* render_frame) { + return new RendererMediaPlayerManager(render_frame); +} + +RendererMediaPlayerManager::RendererMediaPlayerManager( RenderFrame* render_frame) : RenderFrameObserver(render_frame), next_media_player_id_(0) { } -RendererMediaPlayerManagerEfl::~RendererMediaPlayerManagerEfl() { +RendererMediaPlayerManager::~RendererMediaPlayerManager() { DCHECK(media_players_.empty()) - << "RendererMediaPlayerManagerEfl is owned by RenderFrameImpl and is " + << "RendererMediaPlayerManager is owned by RenderFrameImpl and is " "destroyed only after all media players are destroyed."; } -void RendererMediaPlayerManagerEfl::PausePlayingPlayers() { - std::map::iterator player_it; - for (player_it = media_players_.begin();player_it != media_players_.end();) { - media::WebMediaPlayerEfl* player = player_it->second; - // Element pointed by the iterator can get deleted during the function call - // "player->RequestPause()", hence increment the iterator beforehand - ++player_it; +void RendererMediaPlayerManager::PausePlayingPlayers() { + for (auto player_it : media_players_) { + media::WebMediaPlayerEfl* player = player_it.second; if (player && !player->paused() && player->hasVideo()) player->RequestPause(); } } -bool RendererMediaPlayerManagerEfl::OnMessageReceived( +bool RendererMediaPlayerManager::OnMessageReceived( const IPC::Message& message) { bool handled = true; - IPC_BEGIN_MESSAGE_MAP(RendererMediaPlayerManagerEfl, message) - IPC_MESSAGE_HANDLER(MediaPlayerGstMsg_MediaDataChanged, OnMediaDataChange) - IPC_MESSAGE_HANDLER(MediaPlayerGstMsg_DurationChanged, OnDurationChange) - IPC_MESSAGE_HANDLER(MediaPlayerGstMsg_TimeUpdate, OnTimeUpdate) - IPC_MESSAGE_HANDLER(MediaPlayerGstMsg_BufferUpdate, OnBufferUpdate) - IPC_MESSAGE_HANDLER(MediaPlayerGstMsg_ReadyStateChange, OnReadyStateChange) - IPC_MESSAGE_HANDLER(MediaPlayerGstMsg_NetworkStateChange, + IPC_BEGIN_MESSAGE_MAP(RendererMediaPlayerManager, message) + IPC_MESSAGE_HANDLER(MediaPlayerEflMsg_MediaDataChanged, + OnMediaDataChange) + IPC_MESSAGE_HANDLER(MediaPlayerEflMsg_DurationChanged, OnDurationChange) + IPC_MESSAGE_HANDLER(MediaPlayerEflMsg_TimeUpdate, OnTimeUpdate) + IPC_MESSAGE_HANDLER(MediaPlayerEflMsg_BufferUpdate, OnBufferUpdate) + IPC_MESSAGE_HANDLER(MediaPlayerEflMsg_ReadyStateChange, + OnReadyStateChange) + IPC_MESSAGE_HANDLER(MediaPlayerEflMsg_NetworkStateChange, OnNetworkStateChange) - IPC_MESSAGE_HANDLER(MediaPlayerGstMsg_TimeChanged, OnTimeChanged) - IPC_MESSAGE_HANDLER(MediaPlayerGstMsg_OnPauseStateChange, - OnPauseStateChange) - IPC_MESSAGE_HANDLER(MediaPlayerGstMsg_OnSeekStateChange, OnSeekStateChange) - IPC_MESSAGE_HANDLER(MediaPlayerGstMsg_SeekRequest, OnRequestSeek) - IPC_MESSAGE_HANDLER(MediaPlayerGstMsg_NewFrameAvailable, + IPC_MESSAGE_HANDLER(MediaPlayerEflMsg_TimeChanged, OnTimeChanged) + IPC_MESSAGE_HANDLER(MediaPlayerEflMsg_OnSeekStateChange, + OnSeekStateChange) + IPC_MESSAGE_HANDLER(MediaPlayerEflMsg_SeekRequest, OnRequestSeek) + IPC_MESSAGE_HANDLER(MediaPlayerEflMsg_NewFrameAvailable, OnNewFrameAvailable) #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) - IPC_MESSAGE_HANDLER(MediaPlayerGstMsg_PlatformSurfaceUpdated, + IPC_MESSAGE_HANDLER(MediaPlayerEflMsg_PlatformSurfaceUpdated, OnPlatformSurfaceUpdated) #endif IPC_MESSAGE_UNHANDLED(handled = false) @@ -62,28 +63,33 @@ bool RendererMediaPlayerManagerEfl::OnMessageReceived( return handled; } -void RendererMediaPlayerManagerEfl::Initialize( +void RendererMediaPlayerManager::WasHidden() { + PausePlayingPlayers(); +} + +void RendererMediaPlayerManager::OnStop() { + PausePlayingPlayers(); +} + +void RendererMediaPlayerManager::Initialize( int player_id, MediaPlayerHostMsg_Initialize_Type type, const GURL& url, double volume, int demuxer_client_id) { - Send(new MediaPlayerGstHostMsg_Init( - routing_id(), player_id, type, url, volume, demuxer_client_id)); + Send(new MediaPlayerEflHostMsg_Init(routing_id(), player_id, type, + url, volume, demuxer_client_id)); } -void RendererMediaPlayerManagerEfl::OnMediaDataChange( - int player_id, - int format, - int height, - int width, - int media) { +void RendererMediaPlayerManager::OnMediaDataChange(int player_id, int format, + int height, int width, + int media) { media::WebMediaPlayerEfl* player = GetMediaPlayer(player_id); if (player) player->OnMediaDataChange(format, height, width, media); } -void RendererMediaPlayerManagerEfl::OnDurationChange( +void RendererMediaPlayerManager::OnDurationChange( int player_id, double duration) { media::WebMediaPlayerEfl* player = GetMediaPlayer(player_id); @@ -91,7 +97,7 @@ void RendererMediaPlayerManagerEfl::OnDurationChange( player->OnDurationChange(duration); } -void RendererMediaPlayerManagerEfl::OnTimeUpdate( +void RendererMediaPlayerManager::OnTimeUpdate( int player_id, double current_time) { media::WebMediaPlayerEfl* player = GetMediaPlayer(player_id); @@ -99,7 +105,7 @@ void RendererMediaPlayerManagerEfl::OnTimeUpdate( player->OnTimeUpdate(current_time); } -void RendererMediaPlayerManagerEfl::OnBufferUpdate( +void RendererMediaPlayerManager::OnBufferUpdate( int player_id, std::vector buffer_range) { media::WebMediaPlayerEfl* player = GetMediaPlayer(player_id); @@ -107,7 +113,7 @@ void RendererMediaPlayerManagerEfl::OnBufferUpdate( player->OnBufferUpdate(buffer_range); } -void RendererMediaPlayerManagerEfl::OnReadyStateChange( +void RendererMediaPlayerManager::OnReadyStateChange( int player_id, media::MediaPlayerEfl::ReadyState state) { media::WebMediaPlayerEfl* player = GetMediaPlayer(player_id); @@ -116,7 +122,7 @@ void RendererMediaPlayerManagerEfl::OnReadyStateChange( static_cast(state)); } -void RendererMediaPlayerManagerEfl::OnNetworkStateChange( +void RendererMediaPlayerManager::OnNetworkStateChange( int player_id, media::MediaPlayerEfl::NetworkState state) { media::WebMediaPlayerEfl* player = GetMediaPlayer(player_id); @@ -125,48 +131,44 @@ void RendererMediaPlayerManagerEfl::OnNetworkStateChange( static_cast(state)); } -void RendererMediaPlayerManagerEfl::OnTimeChanged(int player_id) { +void RendererMediaPlayerManager::OnTimeChanged(int player_id) { media::WebMediaPlayerEfl* player = GetMediaPlayer(player_id); if (player) player->OnTimeChanged(); } -void RendererMediaPlayerManagerEfl::OnPauseStateChange( - int player_id, - bool state) { +void RendererMediaPlayerManager::OnSeekStateChange(int player_id, + bool state) { media::WebMediaPlayerEfl* player = GetMediaPlayer(player_id); if (player) - player->OnPauseStateChange(state); + player->OnSeekStateChange(state); } -void RendererMediaPlayerManagerEfl::OnSeekStateChange( - int player_id, - bool state) { +void RendererMediaPlayerManager::OnPauseStateChange(int player_id, + bool state) { media::WebMediaPlayerEfl* player = GetMediaPlayer(player_id); if (player) - player->OnSeekStateChange(state); + player->OnPauseStateChange(state); } -void RendererMediaPlayerManagerEfl::OnRequestSeek( - int player_id, - double seek_time) { +void RendererMediaPlayerManager::OnRequestSeek(int player_id, + double seek_time) { media::WebMediaPlayerEfl* player = GetMediaPlayer(player_id); if (player) player->OnRequestSeek(seek_time); } -void RendererMediaPlayerManagerEfl::OnNewFrameAvailable( +void RendererMediaPlayerManager::OnNewFrameAvailable( int player_id, base::SharedMemoryHandle foreign_memory_handle, uint32 length, base::TimeDelta timestamp) { media::WebMediaPlayerEfl* player = GetMediaPlayer(player_id); - // FIXME: Handle exception for all APIs. if (player) player->OnNewFrameAvailable(foreign_memory_handle, length, timestamp); } #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) -void RendererMediaPlayerManagerEfl::OnPlatformSurfaceUpdated( +void RendererMediaPlayerManager::OnPlatformSurfaceUpdated( int player_id, int pixmap_id, base::TimeDelta timestamp) { @@ -176,53 +178,47 @@ void RendererMediaPlayerManagerEfl::OnPlatformSurfaceUpdated( } #endif -media::WebMediaPlayerEfl* RendererMediaPlayerManagerEfl::GetMediaPlayer( +media::WebMediaPlayerEfl* RendererMediaPlayerManager::GetMediaPlayer( int player_id) { std::map::iterator iter = - media_players_.find(player_id); + media_players_.find(player_id); if (iter != media_players_.end()) return iter->second; - return NULL; } -void RendererMediaPlayerManagerEfl::Play(int player_id) { - Send(new MediaPlayerGstHostMsg_Play(routing_id(), player_id)); +void RendererMediaPlayerManager::Play(int player_id) { + Send(new MediaPlayerEflHostMsg_Play(routing_id(), player_id)); } -void RendererMediaPlayerManagerEfl::Pause( - int player_id, - bool is_media_related_action) { - Send(new MediaPlayerGstHostMsg_Pause(routing_id(), player_id)); +void RendererMediaPlayerManager::Pause(int player_id, + bool is_media_related_action) { + Send(new MediaPlayerEflHostMsg_Pause(routing_id(), player_id)); } -void RendererMediaPlayerManagerEfl::Seek(int player_id, double time) { - Send(new MediaPlayerGstHostMsg_Seek(routing_id(), player_id, time)); +void RendererMediaPlayerManager::Seek(int player_id, double time) { + Send(new MediaPlayerEflHostMsg_Seek(routing_id(), player_id, time)); } -void RendererMediaPlayerManagerEfl::SetVolume(int player_id, double volume) { - Send(new MediaPlayerGstHostMsg_SetVolume(routing_id(), player_id, volume)); +void RendererMediaPlayerManager::SetVolume(int player_id, double volume) { + Send(new MediaPlayerEflHostMsg_SetVolume(routing_id(), player_id, volume)); } -void RendererMediaPlayerManagerEfl::SetRate(int player_id, double rate) { - Send(new MediaPlayerGstHostMsg_SetRate(routing_id(), player_id, rate)); +void RendererMediaPlayerManager::SetRate(int player_id, double rate) { + Send(new MediaPlayerEflHostMsg_SetRate(routing_id(), player_id, rate)); } -void RendererMediaPlayerManagerEfl::DestroyPlayer(int player_id) { - VLOG(1) << "RendererMediaPlayerManagerEfl::" << __FUNCTION__ - << " Plyer-Id = " << player_id; - Send(new MediaPlayerGstHostMsg_DeInit(routing_id(), player_id)); +void RendererMediaPlayerManager::DestroyPlayer(int player_id) { + Send(new MediaPlayerEflHostMsg_DeInit(routing_id(), player_id)); } -int RendererMediaPlayerManagerEfl::RegisterMediaPlayer( +int RendererMediaPlayerManager::RegisterMediaPlayer( media::WebMediaPlayerEfl* player) { media_players_[next_media_player_id_] = player; return next_media_player_id_++; } -void RendererMediaPlayerManagerEfl::UnregisterMediaPlayer(int player_id) { - VLOG(1) << "RendererMediaPlayerManagerEfl::" << __FUNCTION__ - << " Player-Id = " << player_id; +void RendererMediaPlayerManager::UnregisterMediaPlayer(int player_id) { media_players_.erase(player_id); } diff --git a/tizen_src/chromium_impl/content/renderer/media/efl/renderer_media_player_manager_efl.h b/tizen_src/chromium_impl/content/renderer/media/efl/renderer_media_player_manager_efl.h index 7459902..d676ba8 100644 --- a/tizen_src/chromium_impl/content/renderer/media/efl/renderer_media_player_manager_efl.h +++ b/tizen_src/chromium_impl/content/renderer/media/efl/renderer_media_player_manager_efl.h @@ -2,10 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_RENDERER_MEDIA_TIZEN_RENDERER_MEDIA_PLAYER_TIZEN_MANAGER_H_ -#define CONTENT_RENDERER_MEDIA_TIZEN_RENDERER_MEDIA_PLAYER_TIZEN_MANAGER_H_ +#ifndef CONTENT_RENDERER_MEDIA_EFL_RENDERER_MEDIA_PLAYER_MANAGER_EFL_H_ +#define CONTENT_RENDERER_MEDIA_EFL_RENDERER_MEDIA_PLAYER_MANAGER_EFL_H_ + +#include #include "content/public/renderer/render_frame_observer.h" +#include "content/common/media/efl/media_player_messages_enums_efl.h" #include "media/base/efl/media_player_efl.h" #include "media/base/efl/webmediaplayer_efl.h" #include "url/gurl.h" @@ -16,19 +19,15 @@ class WebMediaPlayerEfl; namespace content { -class RendererMediaPlayerManagerEfl : public RenderFrameObserver { +class RendererMediaPlayerManager : public RenderFrameObserver { public: - // Constructs a RendererMediaPlayerManagerEfl object for the |render_frame|. - explicit RendererMediaPlayerManagerEfl(RenderFrame* render_frame); - virtual ~RendererMediaPlayerManagerEfl(); + // Constructs a RendererMediaPlayerManager object for the |render_frame|. + explicit RendererMediaPlayerManager(RenderFrame* render_frame); + ~RendererMediaPlayerManager() override; // Initializes a MediaPlayerEfl object in browser process. - void Initialize( - int player_id, - MediaPlayerHostMsg_Initialize_Type type, - const GURL& url, - double volume, - int demuxer_client_id); + void Initialize(int player_id, MediaPlayerHostMsg_Initialize_Type type, + const GURL& url, double volume, int demuxer_client_id); // Starts the player. void Play(int player_id); @@ -56,32 +55,26 @@ class RendererMediaPlayerManagerEfl : public RenderFrameObserver { int RegisterMediaPlayer(media::WebMediaPlayerEfl* player); void UnregisterMediaPlayer(int player_id); + // RenderFrameObserver overrides. bool OnMessageReceived(const IPC::Message& message) override; + void WasHidden() override; + void OnStop() override; - media::WebMediaPlayerEfl* GetMediaPlayer(int player_id); - - //Pause the playing media players when tab/webpage goes to background + // Pause the playing media players when tab/webpage goes to background void PausePlayingPlayers(); private: - void OnNewFrameAvailable( - int player_id, - base::SharedMemoryHandle foreign_memory_handle, - uint32 length, base::TimeDelta timestamp); + void OnNewFrameAvailable(int player_id, + base::SharedMemoryHandle foreign_memory_handle, + uint32 length, base::TimeDelta timestamp); #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) - void OnPlatformSurfaceUpdated( - int player_id, - int pixmap_id, - base::TimeDelta timestamp); + void OnPlatformSurfaceUpdated(int player_id, int pixmap_id, + base::TimeDelta timestamp); #endif - - void OnMediaDataChange( - int player_id, - int format, - int height, - int width, - int media); + media::WebMediaPlayerEfl* GetMediaPlayer(int player_id); + void OnMediaDataChange(int player_id, int format, int height, + int width, int media); void OnDurationChange(int player_id, double duration); void OnTimeUpdate(int player_id, double current_time); void OnBufferUpdate( @@ -91,21 +84,18 @@ class RendererMediaPlayerManagerEfl : public RenderFrameObserver { void OnPauseStateChange(int player_id, bool state); void OnSeekStateChange(int player_id, bool state); void OnRequestSeek(int player_id, double seek_time); - void OnReadyStateChange( - int player_id, - media::MediaPlayerEfl::ReadyState state ); - void OnNetworkStateChange( - int player_id, - media::MediaPlayerEfl::NetworkState state ); + void OnReadyStateChange(int player_id, + media::MediaPlayerEfl::ReadyState state); + void OnNetworkStateChange(int player_id, + media::MediaPlayerEfl::NetworkState state); private: std::map media_players_; - int next_media_player_id_; - DISALLOW_COPY_AND_ASSIGN(RendererMediaPlayerManagerEfl); + DISALLOW_COPY_AND_ASSIGN(RendererMediaPlayerManager); }; } // namespace content -#endif // CONTENT_RENDERER_MEDIA_TIZEN_RENDERER_MEDIA_PLAYER_TIZEN_MANAGER_H_ +#endif // CONTENT_RENDERER_MEDIA_EFL_RENDERER_MEDIA_PLAYER_MANAGER_EFL_H_ diff --git a/tizen_src/chromium_impl/media/base/efl/demuxer_efl.h b/tizen_src/chromium_impl/media/base/efl/demuxer_efl.h index bb219fe..12bd477 100644 --- a/tizen_src/chromium_impl/media/base/efl/demuxer_efl.h +++ b/tizen_src/chromium_impl/media/base/efl/demuxer_efl.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef MEDIA_BASE_TIZEN_DEMUXER_TIZEN_H_ -#define MEDIA_BASE_TIZEN_DEMUXER_TIZEN_H_ +#ifndef MEDIA_BASE_EFL_DEMUXER_EFL_H_ +#define MEDIA_BASE_EFL_DEMUXER_EFL_H_ #include "media/base/efl/demuxer_stream_player_params_efl.h" @@ -12,9 +12,7 @@ namespace media { // Defines the client callback interface. class MEDIA_EXPORT DemuxerEflClient { public: - - // Called in response to RequestDemuxerConfigs() and also when the demuxer - // has initialized. + // Called when the demuxer has initialized. virtual void OnDemuxerConfigsAvailable(const DemuxerConfigs& params) = 0; // Called in response to RequestDemuxerData(). @@ -22,10 +20,6 @@ class MEDIA_EXPORT DemuxerEflClient { base::SharedMemoryHandle foreign_memory_handle, const media::DemuxedBufferMetaData& meta_data) = 0; - // Called in response to RequestDemuxerData() when no data is available. - virtual void OnBufferMetaDataAvailable( - const media::DemuxedBufferMetaData& meta_data) = 0; - // Called to inform demuxer seek completion. virtual void OnDemuxerSeekDone( const base::TimeDelta& actual_browser_seek_time) = 0; @@ -46,9 +40,6 @@ class MEDIA_EXPORT DemuxerEfl { // Must be called prior to calling any other methods. virtual void Initialize(DemuxerEflClient* client) = 0; - // Called to request the current audio/video decoder configurations. - virtual void RequestDemuxerConfigs() = 0; - // Called to request demuxer seek. virtual void RequestDemuxerSeek(const base::TimeDelta& time_to_seek) = 0; @@ -58,4 +49,4 @@ class MEDIA_EXPORT DemuxerEfl { } // namespace media -#endif // MEDIA_BASE_TIZEN_DEMUXER_TIZEN_H_ +#endif // MEDIA_BASE_EFL_DEMUXER_EFL_H_ \ No newline at end of file diff --git a/tizen_src/chromium_impl/media/base/efl/demuxer_stream_player_params_efl.h b/tizen_src/chromium_impl/media/base/efl/demuxer_stream_player_params_efl.h index 282e0b3..8b69c87 100644 --- a/tizen_src/chromium_impl/media/base/efl/demuxer_stream_player_params_efl.h +++ b/tizen_src/chromium_impl/media/base/efl/demuxer_stream_player_params_efl.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef MEDIA_BASE_TIZEN_DEMUXER_STREAM_PLAYER_PARAMS_EFL_H_ -#define MEDIA_BASE_TIZEN_DEMUXER_STREAM_PLAYER_PARAMS_EFL_H_ +#ifndef MEDIA_BASE_EFL_DEMUXER_STREAM_PLAYER_PARAMS_EFL_H_ +#define MEDIA_BASE_EFL_DEMUXER_STREAM_PLAYER_PARAMS_EFL_H_ #include @@ -48,4 +48,4 @@ struct MEDIA_EXPORT DemuxedBufferMetaData { }; // namespace media -#endif // MEDIA_BASE_TIZEN_DEMUXER_STREAM_PLAYER_PARAMS_TIZEN_H_ +#endif // MEDIA_BASE_EFL_DEMUXER_STREAM_PLAYER_PARAMS_EFL_H_ diff --git a/tizen_src/chromium_impl/media/base/efl/media_player_bridge_gstreamer.cc b/tizen_src/chromium_impl/media/base/efl/media_player_bridge_gstreamer.cc index 092154e..e48e338 100644 --- a/tizen_src/chromium_impl/media/base/efl/media_player_bridge_gstreamer.cc +++ b/tizen_src/chromium_impl/media/base/efl/media_player_bridge_gstreamer.cc @@ -7,129 +7,88 @@ #include #include #include -#include #include "base/basictypes.h" -#include "base/message_loop/message_loop_proxy.h" #include "media/base/efl/media_player_manager_efl.h" +#include "media/base/efl/media_player_util_efl.h" #include "ui/gfx/geometry/size.h" -#if defined(OS_TIZEN_MOBILE) && (defined(TIZEN_V_2_3) || defined(TIZEN_V_2_4)) -#include -#endif - #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) -#if GST_VERSION_MAJOR == 1 +#include #include -#else -#include -#endif #endif namespace { -// fourcc for gst-video-format -const uint32 GST_VIDEO_SN12 = GST_MAKE_FOURCC('S','N','1','2'); - -// tile size for SN12 -const uint SN12_TILE_WIDTH = 64; -const uint SN12_TILE_HEIGHT = 32; -const uint SN12_TILE_SIZE = SN12_TILE_WIDTH * SN12_TILE_HEIGHT; - -// GstPlayFlags in |gstplay-enum.h| -typedef enum { - GST_PLAY_FLAG_VIDEO = (1 << 0), - GST_PLAY_FLAG_AUDIO = (1 << 1), - GST_PLAY_FLAG_TEXT = (1 << 2), - GST_PLAY_FLAG_VIS = (1 << 3), - GST_PLAY_FLAG_SOFT_VOLUME = (1 << 4), - GST_PLAY_FLAG_NATIVE_AUDIO = (1 << 5), - GST_PLAY_FLAG_NATIVE_VIDEO = (1 << 6), - GST_PLAY_FLAG_DOWNLOAD = (1 << 7), - GST_PLAY_FLAG_BUFFERING = (1 << 8), - GST_PLAY_FLAG_DEINTERLACE = (1 << 9), - GST_PLAY_FLAG_SOFT_COLORBALANCE = (1 << 10) -} GstPlayFlags; - -#if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) -typedef enum { - DEGREE_0, // No rotate - DEGREE_90, // Rotate 90 degree count clockwise - DEGREE_180, // Rotate 180 degree count clockwise - DEGREE_270 // Rotate 270 degree count clockwise -} RotateAngle; -#endif - -// Playbin element name -const char* kPlaybinName = "gst_playbin"; +// Element name +const char* kPipelineName = "gst_pipeline"; +const char* kDecodebin = "gst_uridecodebin"; const char* kVideoSink = "gst_video_sink"; +const char* kAudioConverter = "gst_audioconvert"; +const char* kVolume = "gst_volume"; +const char* kAudioSink = "gst_audiosink"; +#if defined(TIZEN_MULTIMEDIA_USE_HW_CODEC) +const char* kVideoConverter = "gst_videoconvert"; +#if defined(OS_TIZEN) +const char* KVideoConvertElement = "fimcconvert"; +#else +const char* KVideoConvertElement = "videoconvert"; +#endif +#endif const char* kPropertyBufferSize = "buffer-size"; -const char* kPropertyMaxBuffers = "max-buffers"; const char* kPropertyVolume = "volume"; const char* kPropertyUri = "uri"; -const char* kPropertyAudioStream = "n-audio"; -const char* kPropertyVideoStream = "n-video"; -const char* kPropertyTextStream = "n-text"; +const char* kPropertyDownload = "download"; // Update duration every 100ms. const int kDurationUpdateInterval = 100; const int kMaxBuffer = 1; - -// sample size for audio/video buffering +const int kMaxBufPercent = 100; +// Buffer size for audio/video buffering. const int kPreloadBufferSize = (3 * 1024 * 1024); // 3MB -const GstClockTime ConvertToGstClockTime(double time) { - if (time < 0) { - LOG(ERROR) << "Invalid time:" << time << " Reset to 0"; - time = 0; - } - - // Extract the integer part of the time (seconds) and the fractional part - // (microseconds). Attempt to round the microseconds so no floating point - // precision is lost and we can perform an accurate seek. - double seconds = 0; - double microSeconds = std::modf(time, &seconds) * 1000000; - GTimeVal timeValue; - timeValue.tv_sec = static_cast(seconds); - timeValue.tv_usec = static_cast(lround(microSeconds / 10) * 10); - return GST_TIMEVAL_TO_TIME(timeValue); -} +#define GST_OBJECT_UNREF(obj) \ + if (obj) { \ + gst_object_unref(obj); \ + obj = NULL; \ + } -const double ConvertNanoSecondsToSeconds(int64 time) { - double seconds = static_cast(time) / - (base::Time::kNanosecondsPerSecond); - return seconds; -} +struct GstElementDeleter { + void operator()(GstElement* ptr) const { + GST_OBJECT_UNREF(ptr); + } +}; } // namespace namespace media { #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) -static Eina_Bool notify_damage_updated_cb(void* data, int type, void* event) { +static Eina_Bool NotifyDamageUpdatedCB(void* data, int type, void* event) { MediaPlayerBridgeGstreamer* player = - static_cast (data); + static_cast(data); if (!player) return ECORE_CALLBACK_PASS_ON; - player->PlatformSurfaceUpdated(); return ECORE_CALLBACK_PASS_ON; } -static int get_pixmap_id_cb(void* data) { +#if defined(OS_TIZEN_TV) +static int GetPixmapIdCB(void* data) { MediaPlayerBridgeGstreamer* player = - static_cast (data); + static_cast(data); return player->GetSurfaceID(); } #endif +#endif -static GstBusSyncReply gst_pipeline_message_cb( +static GstBusSyncReply GstPipelineMessageCB( GstBus* bus, GstMessage* message, gpointer user_data) { MediaPlayerBridgeGstreamer* player = static_cast(user_data); - if (!player) + if (!player || player->IsPlayerDestructing()) return GST_BUS_PASS; player->HandleMessage(message); @@ -137,45 +96,61 @@ static GstBusSyncReply gst_pipeline_message_cb( return GST_BUS_DROP; } -static void on_gst_appsink_eos( - GstAppSink* appsink, - gpointer user_data) { - // EOS is Handled in state handling. Do nothing. -} - -// Audio part of GStreamer is not yet implemented. Workaround to handle -// |PREROLLED| for audio files is to update based on |GST_MESSAGE_BUFFERING|. -static GstFlowReturn on_gst_appsink_preroll( +static GstFlowReturn OnGstAppsinkPrerollCB( GstAppSink* sink, gpointer user_data) { MediaPlayerBridgeGstreamer* player = static_cast(user_data); - if (!player) + if (!player || player->IsPlayerDestructing()) return GST_FLOW_ERROR; player->PrerollComplete(); return GST_FLOW_OK; } -static GstFlowReturn on_gst_appsink_sample( +static GstFlowReturn OnGstAppsinkSampleCB( GstAppSink* sink, gpointer user_data) { MediaPlayerBridgeGstreamer* player = static_cast(user_data); - if (!player) + if (!player || player->IsPlayerDestructing()) return GST_FLOW_ERROR; player->SampleReady(player->PullSample()); return GST_FLOW_OK; } -static void on_gst_installer_result_function( - GstInstallPluginsReturn result, - gpointer userData) { +static void GstPipelinePadAddedCB(GstElement* src, + GstPad* new_pad, + gpointer user_data) { MediaPlayerBridgeGstreamer* player = - reinterpret_cast(userData); - player->HandlePluginInstallerResult(result); + static_cast(user_data); + DCHECK(player); + player->OnNewPadAdded(new_pad); } +static void GstPipelineNoMorePadsCB(GstElement* src, + gpointer user_data) { + MediaPlayerBridgeGstreamer* player = + static_cast(user_data); + DCHECK(player); + player->OnNoMorePadsAvailable(); +} + +#if !defined(TIZEN_MULTIMEDIA_USE_HW_CODEC) +static GstAutoplugSelectResult +GstUribinFactorySelectCB(GstElement* /*bin*/, GstPad* /*pad*/, + GstCaps* /*caps*/, GstElementFactory* factory, + gpointer /*user_data*/) { + + if (g_str_has_prefix(GST_OBJECT_NAME(factory), "omxh264") || + g_str_has_prefix(GST_OBJECT_NAME(factory), "v4l2video6dec") ) { + LOG(INFO) << "Skipping omxh264/v4l2video6dec decoder to use S/W Path"; + return GST_AUTOPLUG_SELECT_SKIP; + } + return GST_AUTOPLUG_SELECT_TRY; +} +#endif + MediaPlayerBridgeGstreamer::MediaPlayerBridgeGstreamer( int player_id, const GURL& url, @@ -183,12 +158,20 @@ MediaPlayerBridgeGstreamer::MediaPlayerBridgeGstreamer( MediaPlayerManager* manager_in) : MediaPlayerEfl(player_id, manager_in), main_loop_(base::MessageLoopProxy::current()), - gst_playbin_(NULL), - gst_appsink_(NULL), + pipeline_(NULL), + appsink_(NULL), + uridecodebinsrc_(NULL), +#if defined(TIZEN_MULTIMEDIA_USE_HW_CODEC) + video_convert_(NULL), +#endif + audio_convert_(NULL), + audio_volume_(NULL), + audio_sink_(NULL), + audio_sinkpad_(NULL), + video_sinkpad_(NULL), url_(url), - volume_(volume), - gst_width_(0), - gst_height_(0), + width_(0), + height_(0), is_prerolled_(false), is_paused_(true), duration_(0), @@ -200,105 +183,41 @@ MediaPlayerBridgeGstreamer::MediaPlayerBridgeGstreamer( is_file_url_(false), is_end_reached_(false), is_seeking_(false), - is_seek_pending_(false), seek_duration_(0), - error_occured_(false), - missing_plugins_(false), - is_pixmap_used_(false), #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) pixmap_id_(0), efl_pixmap_(NULL), - m_damage(0), - m_damageHandler(NULL), + m_damage_(0), + m_damage_handler_(NULL), #endif - bufsize_sn12_(0), - shared_memory_size(0) { - LOG(INFO) << "MediaPlayerBridgeGstreamer - URL = " << url_.spec().c_str(); - - // gstreamer port + error_occured_(false) { if (!gst_is_initialized()) { - gst_init_check(NULL, NULL, 0); - } - - if (gst_is_initialized()) { -#if GST_VERSION_MAJOR == 1 - gst_playbin_ = gst_element_factory_make("playbin", kPlaybinName); -#else - gst_playbin_ = gst_element_factory_make("playbin2", kPlaybinName); -#endif - gst_appsink_ = GetVideoSink(); - if (gst_playbin_ && gst_appsink_) { - g_object_set(gst_playbin_, "video-sink", gst_appsink_, NULL); - - // QoS property will enable the quality-of-service features of the - // basesink which gather statistics about the real-time performance - // of the clock synchronisation. For each sample received in the sink, - // statistics are gathered and a QOS event is sent upstream with - // these numbers. This information can then be used by upstream - // elements to reduce their processing rate, for example. - if(!gst_base_sink_is_qos_enabled(GST_BASE_SINK(gst_appsink_))) - gst_base_sink_set_qos_enabled(GST_BASE_SINK(gst_appsink_), true); - - GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(gst_playbin_)); - if (!bus) { - LOG(ERROR) << "GStreamer bus creation failed"; - HandleError(MediaPlayerEfl::NetworkStateDecodeError); - return; - } -#if GST_VERSION_MAJOR == 1 - gst_bus_set_sync_handler( - bus, (GstBusSyncHandler)gst_pipeline_message_cb, this, NULL); -#else - gst_bus_set_sync_handler( - bus, (GstBusSyncHandler)gst_pipeline_message_cb, this); -#endif - gst_object_unref (bus); - -#if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) - PrepareForVideoSink(); -#else - PrepareForVideoFrame(); -#endif - - g_object_set(G_OBJECT(gst_playbin_), kPropertyVolume, volume_, NULL); - g_object_set( - G_OBJECT(gst_playbin_), kPropertyUri, url_.spec().c_str(), NULL); - - if (gst_element_set_state( - gst_playbin_, GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) - LOG(ERROR) << "GStreamer state change failed"; - - manager()->OnReadyStateChange( - GetPlayerId(), MediaPlayerEfl::ReadyStateHaveEnoughData); - manager()->OnNetworkStateChange( - GetPlayerId(), MediaPlayerEfl::NetworkStateLoaded); - - if(url_.SchemeIsFile()) - is_file_url_ = true; - } else { - if (gst_playbin_) { - gst_object_unref(gst_playbin_); - gst_playbin_ = NULL; - } - if(gst_appsink_) { - gst_object_unref(gst_appsink_); - gst_appsink_ = NULL; - } - LOG(ERROR) << "Unable to create GStreamer elements"; + if (!gst_init_check(NULL, NULL, 0)) { + LOG(ERROR) << "Unable to initialize GST"; HandleError(MediaPlayerEfl::NetworkStateDecodeError); + return; } - } else { - LOG(ERROR) << "Unable to initialize GST"; + } + + if (!InitPipeline()) { HandleError(MediaPlayerEfl::NetworkStateDecodeError); + return; } -} -MediaPlayerBridgeGstreamer::~MediaPlayerBridgeGstreamer() { - VLOG(1) << __FUNCTION__ << " : Player Id = " << GetPlayerId(); + if (gst_element_set_state(pipeline_, GST_STATE_PAUSED) == + GST_STATE_CHANGE_FAILURE) + LOG(ERROR) << "GStreamer state change failed"; + + manager()->OnReadyStateChange( + GetPlayerId(), MediaPlayerEfl::ReadyStateHaveNothing); + manager()->OnNetworkStateChange( + GetPlayerId(), MediaPlayerEfl::NetworkStateLoading); + + if (url_.SchemeIsFile()) + is_file_url_ = true; } void MediaPlayerBridgeGstreamer::Destroy() { - VLOG(1) << __FUNCTION__ << " : Player Id = " << GetPlayerId(); if (IsPlayerDestructing()) return; @@ -308,24 +227,21 @@ void MediaPlayerBridgeGstreamer::Destroy() { } void MediaPlayerBridgeGstreamer::Play() { - VLOG(1) << __FUNCTION__ << " : Player Id = " << GetPlayerId(); - if (!gst_playbin_) - return; - if (error_occured_ || is_end_reached_) + if (!pipeline_ || error_occured_ || is_end_reached_) return; + if (playback_rate_ == 0.0) { is_paused_ = false; return; } - if (gst_element_set_state( - gst_playbin_, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { + if (gst_element_set_state(pipeline_, GST_STATE_PLAYING) == + GST_STATE_CHANGE_FAILURE) { LOG(ERROR) << "GStreamer state change failed in PLAY"; return; } -#if defined(OS_TIZEN_MOBILE) && (defined(TIZEN_V_2_3) || defined(TIZEN_V_2_4)) - if (device_power_request_lock(POWER_LOCK_DISPLAY, 0) != DEVICE_ERROR_NONE) - LOG(ERROR) << "|device_power_request_lock| request failed"; +#if defined(OS_TIZEN_MOBILE) + WakeUpDisplayAndAcquireDisplayLock(); #endif StartCurrentTimeUpdateTimer(); @@ -334,20 +250,17 @@ void MediaPlayerBridgeGstreamer::Play() { } void MediaPlayerBridgeGstreamer::Pause(bool is_media_related_action) { - VLOG(1) << __FUNCTION__ << " : Player Id = " << GetPlayerId(); - if (!gst_playbin_) - return; - if (error_occured_) + if (!pipeline_ || error_occured_) return; - if (gst_element_set_state( - gst_playbin_, GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) { + + if (gst_element_set_state(pipeline_, GST_STATE_PAUSED) == + GST_STATE_CHANGE_FAILURE) { LOG(ERROR) << "GStreamer state change failed in PAUSE"; return; } -#if defined(OS_TIZEN_MOBILE) && (defined(TIZEN_V_2_3) || defined(TIZEN_V_2_4)) - if (device_power_release_lock(POWER_LOCK_DISPLAY) != DEVICE_ERROR_NONE) - LOG(ERROR) << "|device_power_release_lock| request failed"; +#if defined(OS_TIZEN_MOBILE) + ReleaseDisplayLock(); #endif StopCurrentTimeUpdateTimer(); @@ -355,19 +268,12 @@ void MediaPlayerBridgeGstreamer::Pause(bool is_media_related_action) { } void MediaPlayerBridgeGstreamer::SetRate(double rate) { - VLOG(1) << __FUNCTION__ << "Rate (" << rate << ")"; - if (!gst_playbin_) - return; - if (error_occured_) - return; - if (playback_rate_ == rate) - return; - if (is_live_stream_) + if (error_occured_ || is_live_stream_ || (playback_rate_ == rate)) return; GstState state = GST_STATE_NULL; GstState pending = GST_STATE_NULL; - gst_element_get_state(gst_playbin_, &state, &pending, 0); + gst_element_get_state(pipeline_, &state, &pending, 0); if ((state != GST_STATE_PLAYING && state != GST_STATE_PAUSED) || (pending == GST_STATE_PAUSED)) return; @@ -377,44 +283,39 @@ void MediaPlayerBridgeGstreamer::SetRate(double rate) { return; } - // If rate was zero and requested rate is non-zero, change the paused state - if(playback_rate_ == 0.0 && rate != 0.0) { + // If rate was zero and requested rate is non-zero, change player state + if (playback_rate_ == 0.0 && rate != 0.0) { Play(); StartCurrentTimeUpdateTimer(); } double current_position = GetCurrentTime() * GST_SECOND; - if (rate < 0 && current_position == 0.0f) current_position = -1.0f; - if (SeekTo( - current_position, rate, - static_cast(GST_SEEK_FLAG_FLUSH))) { - - // FIXME: Is is required to mute at abnormal playback rate? + if (SeekTo(ConvertToGstClockTime(current_position), + rate, GST_SEEK_FLAG_FLUSH)) { playback_rate_ = rate; } else { - LOG(ERROR) << "Setting Rate " << rate << " failed"; + LOG(ERROR) << "Setting Rate : " << rate << " failed"; HandleError(MediaPlayerEfl::NetworkStateDecodeError); } } void MediaPlayerBridgeGstreamer::Seek(const double time) { - VLOG(1) << __FUNCTION__ << "Time (" << time<< ")"; - if (IsPlayerDestructing()) return; - if (!gst_playbin_ || error_occured_ || is_live_stream_ || + if (!pipeline_ || error_occured_ || is_live_stream_ || time == GetCurrentTime()) { - main_loop_->PostTask(FROM_HERE, base::Bind( - &MediaPlayerBridgeGstreamer::OnTimeChanged, base::Unretained(this))); + main_loop_->PostTask(FROM_HERE, + base::Bind(&MediaPlayerBridgeGstreamer::OnTimeChanged, + base::Unretained(this))); return; } GstState state = GST_STATE_NULL; GstStateChangeReturn ret = gst_element_get_state( - gst_playbin_, &state, NULL, 250 * GST_NSECOND); + pipeline_, &state, NULL, 250 * GST_NSECOND); if (ret == GST_STATE_CHANGE_FAILURE || ret == GST_STATE_CHANGE_NO_PREROLL) { LOG(ERROR) << "Cannot seek in " << gst_element_state_change_return_get_name(ret) << " state"; @@ -422,9 +323,9 @@ void MediaPlayerBridgeGstreamer::Seek(const double time) { } StopCurrentTimeUpdateTimer(); - if (SeekTo( - ConvertToGstClockTime(time), playback_rate_, static_cast - (GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE))) { + if (SeekTo(ConvertToGstClockTime(time), + playback_rate_, static_cast( + GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE))) { UpdateSeekState(true); seek_duration_ = time; is_end_reached_ = time != duration_ ? false : true; @@ -432,7 +333,7 @@ void MediaPlayerBridgeGstreamer::Seek(const double time) { if (!is_paused_) StartCurrentTimeUpdateTimer(); } else { - LOG(ERROR) << "MediaPlayerBridgeGstreamer::" << __FUNCTION__<<": Failed!"; + LOG(ERROR) << "MediaPlayerBridgeGstreamer::" << __FUNCTION__ << " Failed!"; manager()->OnTimeUpdate(GetPlayerId(), GetCurrentTime()); manager()->OnTimeChanged(GetPlayerId()); } @@ -448,48 +349,162 @@ bool MediaPlayerBridgeGstreamer::SeekTo( endTime = GST_CLOCK_TIME_NONE; } else { startTime = 0; - // If we are at beginning of media, start from the end to - // avoid immediate EOS. - if (position < 0) + // If we are at beginning of media, start from the end to avoid + // immediate EOS. + if (position < 0) { endTime = static_cast(GetCurrentTime() * GST_SECOND); - else + } else { endTime = position; + } } - return gst_element_seek(gst_playbin_, rate, GST_FORMAT_TIME, seekType, - GST_SEEK_TYPE_SET, startTime, GST_SEEK_TYPE_SET, endTime); + return gst_element_seek(pipeline_, rate, GST_FORMAT_TIME, seekType, + GST_SEEK_TYPE_SET, startTime, GST_SEEK_TYPE_SET, + endTime); +} + +bool MediaPlayerBridgeGstreamer::InitPipeline() { + scoped_ptr pipeline; + pipeline.reset(gst_pipeline_new(kPipelineName)); + appsink_ = GetVideoSink(); + if (!gst_bin_add(GST_BIN(pipeline.get()), appsink_)) { + GST_OBJECT_UNREF(appsink_); + return false; + } + uridecodebinsrc_ = gst_element_factory_make("uridecodebin", kDecodebin); + if (!gst_bin_add(GST_BIN(pipeline.get()), uridecodebinsrc_)) { + GST_OBJECT_UNREF(uridecodebinsrc_); + return false; + } +#if defined(TIZEN_MULTIMEDIA_USE_HW_CODEC) + video_convert_ = + gst_element_factory_make(KVideoConvertElement, kVideoConverter); + if (!gst_bin_add(GST_BIN(pipeline.get()), video_convert_)) { + GST_OBJECT_UNREF(video_convert_); + return false; + } + video_sinkpad_ = gst_element_get_static_pad(video_convert_, "sink"); +#else + video_sinkpad_ = gst_element_get_static_pad(appsink_, "sink"); +#endif + audio_convert_ = gst_element_factory_make("audioconvert", kAudioConverter); + if (!gst_bin_add(GST_BIN(pipeline.get()), audio_convert_)) { + GST_OBJECT_UNREF(audio_convert_); + return false; + } + audio_volume_ = gst_element_factory_make("volume", kVolume); + if (!gst_bin_add(GST_BIN(pipeline.get()), audio_volume_)) { + GST_OBJECT_UNREF(audio_volume_); + return false; + } + g_object_set(G_OBJECT(audio_volume_), "mute", false, NULL); + + audio_sink_ = gst_element_factory_make("autoaudiosink", kAudioSink); + if (!gst_bin_add(GST_BIN(pipeline.get()), audio_sink_)) { + GST_OBJECT_UNREF(audio_sink_); + return false; + } + audio_sinkpad_ = gst_element_get_static_pad(audio_convert_, "sink"); + + g_signal_connect(uridecodebinsrc_, "pad-added", + G_CALLBACK(GstPipelinePadAddedCB), this); + g_signal_connect(uridecodebinsrc_, "no-more-pads", + G_CALLBACK(GstPipelineNoMorePadsCB), this); +#if !defined(TIZEN_MULTIMEDIA_USE_HW_CODEC) + g_signal_connect(uridecodebinsrc_, "autoplug-select", + G_CALLBACK(GstUribinFactorySelectCB), this); +#endif + // QoS property will enable quality-of-service features of basesink + // that gather statistics about real-time performance of the clock + // synchronisation. For each buffer received in sink, statistics are + // gathered and a QOS event is sent upstream. This information can + // then be used by upstream elements to reduce their processing rate. + if (!gst_base_sink_is_qos_enabled(GST_BASE_SINK(appsink_))) + gst_base_sink_set_qos_enabled(GST_BASE_SINK(appsink_), true); + + GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline.get())); + if (!bus) { + LOG(ERROR) << "GStreamer bus creation failed"; + return false; + } + gst_bus_set_sync_handler( + bus, + static_cast(GstPipelineMessageCB), + this, + NULL); + gst_object_unref(bus); + +#if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) + PrepareForVideoSink(); +#else + PrepareForVideoFrame(); +#endif + + g_object_set(G_OBJECT(uridecodebinsrc_), + kPropertyDownload, true, kPropertyBufferSize, + kPreloadBufferSize, kPropertyUri, + url_.spec().c_str(), NULL); + pipeline_ = pipeline.release(); + return true; } void MediaPlayerBridgeGstreamer::Release() { - VLOG(1) << __FUNCTION__ << " : Player Id = " << GetPlayerId(); StopCurrentTimeUpdateTimer(); StopBufferingUpdateTimer(); - if (gst_playbin_) { - GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(gst_playbin_)); + if (pipeline_) { + GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline_)); if (bus) { g_signal_handlers_disconnect_by_func( - bus, reinterpret_cast(gst_pipeline_message_cb), this); -#if GST_VERSION_MAJOR == 1 + bus, reinterpret_cast(GstPipelineMessageCB), this); gst_bus_set_sync_handler(bus, NULL, NULL, NULL); -#else - gst_bus_set_sync_handler(bus, NULL, NULL); -#endif gst_object_unref(bus); } - gst_element_set_state(gst_playbin_, GST_STATE_NULL); - gst_object_unref(gst_playbin_); - gst_playbin_ = NULL; - gst_appsink_ = NULL; + manager()->OnReadyStateChange( + GetPlayerId(), MediaPlayerEfl::ReadyStateHaveNothing); + manager()->OnNetworkStateChange( + GetPlayerId(), MediaPlayerEfl::NetworkStateEmpty); + + gst_element_set_state(pipeline_, GST_STATE_NULL); + + if (uridecodebinsrc_) { + g_signal_handlers_disconnect_by_func( + uridecodebinsrc_, + reinterpret_cast(GstPipelinePadAddedCB), + this); + g_signal_handlers_disconnect_by_func( + uridecodebinsrc_, + reinterpret_cast(GstPipelineNoMorePadsCB), + this); +#if !defined(TIZEN_MULTIMEDIA_USE_HW_CODEC) + g_signal_handlers_disconnect_by_func( + uridecodebinsrc_, + reinterpret_cast(GstUribinFactorySelectCB), + this); +#endif + } + + gst_object_unref(pipeline_); + pipeline_ = NULL; + appsink_ = NULL; + uridecodebinsrc_ = NULL; + audio_sink_ = NULL; + audio_convert_ = NULL; +#if defined(TIZEN_MULTIMEDIA_USE_HW_CODEC) + video_convert_ = NULL; +#endif + audio_volume_ = NULL; + audio_sinkpad_ = NULL; + video_sinkpad_ = NULL; } #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) - if (m_damage) { - ecore_x_damage_free(m_damage); - m_damage = 0; + if (m_damage_) { + ecore_x_damage_free(m_damage_); + m_damage_ = 0; } - if (m_damageHandler) { - ecore_event_handler_del(m_damageHandler); - m_damageHandler = NULL; + if (m_damage_handler_) { + ecore_event_handler_del(m_damage_handler_); + m_damage_handler_ = NULL; } if (efl_pixmap_.get()) { efl_pixmap_ = NULL; @@ -498,28 +513,8 @@ void MediaPlayerBridgeGstreamer::Release() { } void MediaPlayerBridgeGstreamer::SetVolume(double volume) { - g_object_set(G_OBJECT(gst_playbin_), kPropertyVolume, volume, NULL); -} - -void MediaPlayerBridgeGstreamer::UpdateMediaType() { - int audio_stream_count = 0; - int video_stream_count = 0; - int text_stream_count = 0; - - g_object_get( - G_OBJECT(gst_playbin_), kPropertyAudioStream, &audio_stream_count, NULL); - g_object_get( - G_OBJECT(gst_playbin_), kPropertyVideoStream, &video_stream_count, NULL); - g_object_get( - G_OBJECT(gst_playbin_), kPropertyTextStream, &text_stream_count, NULL); - media_type_ = ((audio_stream_count ? MEDIA_AUDIO_MASK : 0) | - (video_stream_count ? MEDIA_VIDEO_MASK : 0)); - - // For Video-Sink Implementation we won't be getting Prepare-xid if we have - // only audio. - if (is_pixmap_used_ && video_stream_count == 0) - manager()->OnMediaDataChange( - GetPlayerId(), video_format_, gst_height_, gst_width_, media_type_); + CHECK(volume >= 0.0f && volume <= 1.0f); + g_object_set(G_OBJECT(audio_volume_), kPropertyVolume, volume, NULL); } void MediaPlayerBridgeGstreamer::UpdateDuration() { @@ -528,15 +523,12 @@ void MediaPlayerBridgeGstreamer::UpdateDuration() { gint64 duration = 0; GstFormat format = GST_FORMAT_TIME; -#if GST_VERSION_MAJOR == 1 - gst_element_query_duration(gst_playbin_, format, &duration); -#else - gst_element_query_duration(gst_playbin_, &format, &duration); -#endif + gst_element_query_duration(pipeline_, format, &duration); duration_ = ConvertNanoSecondsToSeconds(duration); manager()->OnDurationChange(GetPlayerId(), duration_); - // No need to sample 'local file'. Update buffered percentage. - if(is_file_url_) { + + // No need to buffer 'local file'. Update buffered percentage. + if (is_file_url_) { std::vector buffer_range; media::MediaPlayerEfl::TimeRanges range; range.start = 0; @@ -554,31 +546,13 @@ double MediaPlayerBridgeGstreamer::GetCurrentTime() { GstFormat format = GST_FORMAT_TIME; if (is_end_reached_) { - // Position queries on a null pipeline return 0. If we're at - // the end of the stream the pipeline is null but we want to - // report either the seek time or the duration because this is - // what the Media element spec expects us to do. if (is_seeking_) return seek_duration_; - - // Workaround for - // https://bugzilla.gnome.org/show_bug.cgi?id=639941 In GStreamer - // 0.10.35 basesink reports wrong duration in case of EOS and - // negative playback rate. There's no upstream accepted patch for - // this bug yet, hence this temporary workaround. - if (playback_rate_ < 0) - return 0.0f; if (duration_) return duration_; - - // FIXME: Should null be sent here? } -#if GST_VERSION_MAJOR == 1 - gst_element_query_position(gst_playbin_, format, ¤t_time); -#else - gst_element_query_position(gst_playbin_, &format, ¤t_time); -#endif + gst_element_query_position(pipeline_, format, ¤t_time); return ConvertNanoSecondsToSeconds(current_time); } @@ -620,9 +594,8 @@ void MediaPlayerBridgeGstreamer::StopBufferingUpdateTimer() { buffering_update_timer_.Stop(); } -#if GST_VERSION_MAJOR == 1 GstSample* MediaPlayerBridgeGstreamer::PullSample() { - return gst_app_sink_pull_sample(GST_APP_SINK(gst_appsink_)); + return gst_app_sink_pull_sample(GST_APP_SINK(appsink_)); } void MediaPlayerBridgeGstreamer::SampleReady(GstSample* sample) { @@ -630,108 +603,70 @@ void MediaPlayerBridgeGstreamer::SampleReady(GstSample* sample) { GstBuffer* buffer = gst_sample_get_buffer(sample); if (!gst_buffer_map(buffer, &map, GST_MAP_READ)) { - LOG (ERROR) << "Sample contains invalid or no info!"; + LOG(ERROR) << "Sample contains invalid or no info!"; + gst_sample_unref(sample); return; } - if (!gst_width_ || !gst_height_) + if (!width_ || !height_) GetFrameDetails(); + base::SharedMemory shared_memory; + uint32 shared_memory_size = 0; + base::SharedMemoryHandle foreign_memory_handle; + base::TimeDelta timestamp = base::TimeDelta::FromMicroseconds( GST_BUFFER_TIMESTAMP(buffer) / base::Time::kNanosecondsPerMicrosecond); if (video_format_ == GST_VIDEO_SN12) - shared_memory_size = (bufsize_sn12_); + shared_memory_size = GetSN12BufferSize(width_, height_); else shared_memory_size = (map.size); if (!shared_memory.CreateAndMapAnonymous(shared_memory_size)) { - LOG (ERROR) << "Shared Memory creation failed."; + LOG(ERROR) << "Shared Memory creation failed."; gst_buffer_unmap(buffer, &map); gst_sample_unref(sample); return; } if (!shared_memory.ShareToProcess( - base::Process::Current().Handle(), &foreign_memory_handle)) { - LOG (ERROR) << "Shared Memory handle could not be obtained"; - shared_memory.Close(); + base::Process::Current().Handle(), &foreign_memory_handle)) { + LOG(ERROR) << "Shared Memory handle could not be obtained"; gst_buffer_unmap(buffer, &map); gst_sample_unref(sample); return; } + memcpy(shared_memory.memory(), map.data, shared_memory_size); + // FIMCCONVERT gives extra 12 bytes for yuv_size +#if defined(TIZEN_MULTIMEDIA_USE_HW_CODEC) + shared_memory_size -= 12; +#endif + manager()->OnNewFrameAvailable( GetPlayerId(), foreign_memory_handle, shared_memory_size, timestamp); - shared_memory.Close(); gst_buffer_unmap(buffer, &map); gst_sample_unref(sample); } -#else -GstBuffer* MediaPlayerBridgeGstreamer::PullSample() { - return gst_app_sink_pull_buffer(GST_APP_SINK(gst_appsink_)); -} - -void MediaPlayerBridgeGstreamer::SampleReady( - const GstBuffer* buffer) { - if (!GST_BUFFER_DATA(buffer) || !GST_BUFFER_SIZE(buffer)) - return; - - if (!gst_width_ || !gst_height_) - GetFrameDetails(); - // FIXME: Cross check the end results. - - base::TimeDelta timestamp = base::TimeDelta::FromMicroseconds( - GST_BUFFER_TIMESTAMP(buffer) / base::Time::kNanosecondsPerMicrosecond); - - uint8* buffer_data = GST_BUFFER_DATA(buffer); - gsize buffer_size = GST_BUFFER_SIZE(buffer); - if (video_format_ == GST_VIDEO_SN12) { - shared_memory_size = (bufsize_sn12_); - } else { - shared_memory_size = (buffer_size); - } - if (!shared_memory.CreateAndMapAnonymous(shared_memory_size)) { - LOG (ERROR) << "Shared Memory creation failed."; - gst_buffer_unref(GST_BUFFER(buffer)); - return; - } - if (!shared_memory.ShareToProcess( - base::Process::Current().Handle(), &foreign_memory_handle)) { - LOG (ERROR) << "Shared Memory handle could not be obtained"; - shared_memory.Close(); - gst_buffer_unref(GST_BUFFER(buffer)); - return; - } - - memcpy(shared_memory.memory(), buffer_data, shared_memory_size); - manager()->OnNewFrameAvailable( - GetPlayerId(), foreign_memory_handle, shared_memory_size, timestamp); - - shared_memory.Close(); - gst_buffer_unref(GST_BUFFER(buffer)); -} -#endif - -// Updates networkState and ReadyState based on buffering percentage. void MediaPlayerBridgeGstreamer::ProcessBufferingStats(GstMessage* message) { if (IsPlayerDestructing()) return; gst_message_parse_buffering(message, &buffered_); - main_loop_->PostTask(FROM_HERE, base::Bind( - &MediaPlayerBridgeGstreamer::OnUpdateStates, base::Unretained(this))); + main_loop_->PostTask(FROM_HERE, + base::Bind(&MediaPlayerBridgeGstreamer::OnUpdateStates, + base::Unretained(this))); } -// To Update Buffered Ranges for Media Playback void MediaPlayerBridgeGstreamer::GetBufferedTimeRanges() { - GstQuery *query = NULL; + GstQuery* query = NULL; gboolean result = false; media::Ranges time_ranges; std::vector buffer_range; - query = gst_query_new_buffering (GST_FORMAT_PERCENT); - result = gst_element_query(gst_playbin_, query); + query = gst_query_new_buffering(GST_FORMAT_PERCENT); + result = gst_element_query(pipeline_, query); if (result) { gint n_ranges = 0, range = 0; n_ranges = gst_query_get_n_buffering_ranges(query); @@ -739,26 +674,12 @@ void MediaPlayerBridgeGstreamer::GetBufferedTimeRanges() { gint64 start = 0, stop = 0; gst_query_parse_nth_buffering_range(query, range, &start, &stop); media::MediaPlayerEfl::TimeRanges b_range; - -#if GST_VERSION_MAJOR == 1 if ((start == 0 || is_end_reached_) && stop == GST_FORMAT_PERCENT_MAX) StopBufferingUpdateTimer(); b_range.start = start * duration_; b_range.end = stop * duration_; -#else - // Stop the Timer on Buffer completion - if(start == 0 && stop == 100) - StopBufferingUpdateTimer(); - - // Parsed value is in percentage. Converted into time range - b_range.start = static_cast(start) * duration_ / 100 - * base::Time::kMicrosecondsPerSecond; - b_range.end = static_cast(stop) * duration_ / 100 - * base::Time::kMicrosecondsPerSecond; -#endif - buffer_range.push_back(b_range); } manager()->OnBufferUpdate(GetPlayerId(), buffer_range); @@ -769,346 +690,229 @@ void MediaPlayerBridgeGstreamer::HandleMessage(GstMessage* message) { if (IsPlayerDestructing()) return; - if (!strcmp(kPlaybinName, GST_MESSAGE_SRC_NAME(message))) - VLOG(1) << "MediaPlayerBridgeGstreamer::" << __FUNCTION__ - << " received from element " << GST_MESSAGE_SRC_NAME(message) - << " ID " << GetPlayerId(); - - const GstStructure* structure = gst_message_get_structure(message); - if (structure) { - const gchar* messageTypeName = gst_structure_get_name(structure); - - // Redirect messages are sent from elements, like qtdemux, to - // notify of the new location(s) of the media. - if (!g_strcmp0(messageTypeName, "redirect")) { - // FIXME: for changing media location - return; - } - } - - //FIXME: Add and handle all conditions switch (GST_MESSAGE_TYPE(message)) { - case GST_MESSAGE_ERROR: - if (missing_plugins_) + case GST_MESSAGE_STREAM_STATUS: + case GST_MESSAGE_TAG: + break; + case GST_MESSAGE_ERROR: { + StopBufferingUpdateTimer(); + GError* error = NULL; + gst_message_parse_error(message, &error, NULL); + MediaPlayerEfl::NetworkState network_state_error; + network_state_error = MediaPlayerEfl::NetworkStateEmpty; + if (error->code == GST_STREAM_ERROR_CODEC_NOT_FOUND + || error->code == GST_STREAM_ERROR_WRONG_TYPE + || error->code == GST_STREAM_ERROR_FAILED + || error->code == GST_CORE_ERROR_MISSING_PLUGIN + || error->code == GST_RESOURCE_ERROR_NOT_FOUND) + network_state_error = MediaPlayerEfl::NetworkStateFormatError; + else if (error->domain == GST_RESOURCE_ERROR) + network_state_error = MediaPlayerEfl::NetworkStateNetworkError; + else + network_state_error = MediaPlayerEfl::NetworkStateDecodeError; + + LOG(ERROR) << "Error Message : " << error->message << " Recieved From : " + << GST_MESSAGE_SRC_NAME(message) + << ", and Blink Error Code : " << network_state_error; + g_error_free(error); + HandleError(network_state_error); break; - - StopBufferingUpdateTimer(); - GError* error; - gst_message_parse_error(message, &error, NULL); - MediaPlayerEfl::NetworkState network_state_error; - network_state_error = MediaPlayerEfl::NetworkStateEmpty; - if (error->code == GST_STREAM_ERROR_CODEC_NOT_FOUND - || error->code == GST_STREAM_ERROR_WRONG_TYPE - || error->code == GST_STREAM_ERROR_FAILED - || error->code == GST_CORE_ERROR_MISSING_PLUGIN - || error->code == GST_RESOURCE_ERROR_NOT_FOUND) { - network_state_error = MediaPlayerEfl::NetworkStateFormatError; - } else if (error->domain == GST_RESOURCE_ERROR) { - network_state_error = MediaPlayerEfl::NetworkStateNetworkError; - } else { - network_state_error = MediaPlayerEfl::NetworkStateDecodeError; } - - LOG(ERROR) << "Error Message : " << error->message << " Recieved From : " - << GST_MESSAGE_SRC_NAME(message) - << ", and Blink Error Code = " << network_state_error; - g_error_free(error); - - HandleError(network_state_error); - break; - case GST_MESSAGE_EOS: - VLOG(1) << "Got GST_MESSAGE_EOS"; - main_loop_->PostTask(FROM_HERE, base::Bind( - &MediaPlayerBridgeGstreamer::OnPlaybackComplete, base::Unretained(this))); - break; - case GST_MESSAGE_ASYNC_DONE: - if (is_seeking_) { - UpdateSeekState(false); - main_loop_->PostTask(FROM_HERE, base::Bind( - &MediaPlayerBridgeGstreamer::OnTimeChanged, base::Unretained(this))); + case GST_MESSAGE_EOS: { + main_loop_->PostTask(FROM_HERE, + base::Bind( + &MediaPlayerBridgeGstreamer::OnPlaybackComplete, + base::Unretained(this))); + break; } + case GST_MESSAGE_ASYNC_DONE: { + if (is_seeking_) { + UpdateSeekState(false); + main_loop_->PostTask(FROM_HERE, + base::Bind( + &MediaPlayerBridgeGstreamer::OnTimeChanged, + base::Unretained(this))); + } - // Without |audio-sink| for audio tracks no preroll message is received. To - // update track details |PrerollComplete| is called. For Video tracks, - // preroll message is received long before control reaches here. - if (!is_prerolled_) - PrerollComplete(); - break; - case GST_MESSAGE_STATE_CHANGED: - if (strcmp(kPlaybinName, GST_MESSAGE_SRC_NAME(message))) + // Without |audio-sink| for audio tracks no preroll message is received. + // To update track details |PrerollComplete| is called. For Video tracks, + // preroll message is received long before control reaches here. + if (!is_prerolled_) + PrerollComplete(); break; - - main_loop_->PostTask(FROM_HERE, base::Bind( - &MediaPlayerBridgeGstreamer::OnUpdateStates, base::Unretained(this))); - break; - case GST_MESSAGE_BUFFERING: + } + case GST_MESSAGE_QOS: { + LOG(INFO) << " QoS received from player : " << GetPlayerId(); + break; + } + case GST_MESSAGE_STATE_CHANGED: { + if (strcmp(kPipelineName, GST_MESSAGE_SRC_NAME(message))) + break; + + main_loop_->PostTask(FROM_HERE, + base::Bind( + &MediaPlayerBridgeGstreamer::OnUpdateStates, + base::Unretained(this))); + break; + } + case GST_MESSAGE_BUFFERING: { ProcessBufferingStats(message); - break; - case GST_MESSAGE_ELEMENT: - if (gst_is_missing_plugin_message(message)) { - gchar* detail = gst_missing_plugin_message_get_installer_detail(message); - gchar* detailArray[2] = {detail, 0}; - GstInstallPluginsReturn result = gst_install_plugins_async( - detailArray, 0, on_gst_installer_result_function, this); - missing_plugins_ = result == GST_INSTALL_PLUGINS_STARTED_OK; - g_free(detail); + break; } - - //gst_message_has_name (msg, "prepare-window-handle") + case GST_MESSAGE_CLOCK_LOST: { + /* Get a new clock */ + gst_element_set_state(pipeline_, GST_STATE_PAUSED); + gst_element_set_state(pipeline_, GST_STATE_PLAYING); + break; + } + case GST_MESSAGE_ELEMENT: #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) - if (!IsXWindowHadleSet() && -#if GST_VERSION_MAJOR == 1 - gst_is_video_overlay_prepare_window_handle_message(message)) { -#else - gst_structure_has_name(message->structure, "prepare-xid")) { + if (!IsXWindowHandleSet()) { + if (message->structure && + gst_is_video_overlay_prepare_window_handle_message(message)) { + XWindowIdPrepared(message); + } + } + break; #endif - LOG(INFO) << "Received message : Video overlay prepared"; - XWindowIdPrepared(message); - gst_message_unref(message); - return; + default: { + LOG(ERROR) << "Unhandled GStreamer message type : " + << GST_MESSAGE_TYPE_NAME(message); + break; } -#endif - break; - default: - LOG(ERROR) << "Unhandled GStreamer message type: " - << GST_MESSAGE_TYPE_NAME(message); - break; - } -} - -void MediaPlayerBridgeGstreamer::HandlePluginInstallerResult( - GstInstallPluginsReturn result) { - missing_plugins_ = false; - if (result == GST_INSTALL_PLUGINS_SUCCESS) { - // FIXME: CAN CAUSE DEADLOCK? - gst_element_set_state(gst_playbin_, GST_STATE_READY); - gst_element_set_state(gst_playbin_, GST_STATE_PAUSED); - } else { - LOG(ERROR) << "GST Plugin Installation failed"; - HandleError(MediaPlayerEfl::NetworkStateDecodeError); } } void MediaPlayerBridgeGstreamer::UpdateStates() { if (IsPlayerDestructing()) return; - if (error_occured_) return; GstState state = GST_STATE_NULL; GstState pending = GST_STATE_NULL; GstStateChangeReturn ret = gst_element_get_state( - gst_playbin_, &state, &pending, 250 * GST_NSECOND); - - VLOG(1) << "MediaPlayerBridgeGstreamer::" - << __FUNCTION__ - << " GstStateChangeReturn: " - << gst_element_state_change_return_get_name(ret) - << " state: " - << gst_element_state_get_name(state) - << " pending: " - << gst_element_state_get_name(pending) - << " ID " << GetPlayerId(); - - // FIXME: Handle all state changes + pipeline_, &state, &pending, 250 * GST_NSECOND); + switch (ret) { - case GST_STATE_CHANGE_SUCCESS: - if (!duration_) - UpdateDuration(); - - switch (state) { - case GST_STATE_NULL: - manager()->OnReadyStateChange( - GetPlayerId(), MediaPlayerEfl::ReadyStateHaveNothing); - manager()->OnNetworkStateChange( - GetPlayerId(), MediaPlayerEfl::NetworkStateEmpty); + case GST_STATE_CHANGE_SUCCESS: { + if (!duration_) + UpdateDuration(); + + switch (state) { + case GST_STATE_VOID_PENDING: + case GST_STATE_NULL: + case GST_STATE_READY: + break; + case GST_STATE_PAUSED: + case GST_STATE_PLAYING: { + if (!is_file_url_) + StartBufferingUpdateTimer(); + + if (buffered_ == kMaxBufPercent || is_file_url_) { + if (state == GST_STATE_PAUSED && !is_paused_) { + if (gst_element_set_state(pipeline_, GST_STATE_PLAYING) == + GST_STATE_CHANGE_FAILURE) + LOG(ERROR) << "GStreamer state change failed"; + } + + // On rapid playback on PIANO Widget, there are instences + // when 'ASYNC-DONE' message is not received on replay. + if (is_seeking_ && state == GST_STATE_PLAYING) { + UpdateSeekState(false); + main_loop_->PostTask( + FROM_HERE, + base::Bind(&MediaPlayerBridgeGstreamer::OnTimeChanged, + base::Unretained(this))); + } + manager()->OnReadyStateChange( + GetPlayerId(), MediaPlayerEfl::ReadyStateHaveEnoughData); + manager()->OnNetworkStateChange( + GetPlayerId(), MediaPlayerEfl::NetworkStateLoaded); + } else { + if (state == GST_STATE_PLAYING) { + if (gst_element_set_state(pipeline_, GST_STATE_PAUSED) == + GST_STATE_CHANGE_FAILURE) + LOG(ERROR) << "GStreamer state change failed"; + manager()->OnReadyStateChange( + GetPlayerId(), MediaPlayerEfl::ReadyStateHaveCurrentData); + manager()->OnNetworkStateChange( + GetPlayerId(), MediaPlayerEfl::NetworkStateLoading); + } + } + break; + } + } break; - case GST_STATE_READY: - manager()->OnReadyStateChange( - GetPlayerId(), MediaPlayerEfl::ReadyStateHaveMetadata); - manager()->OnNetworkStateChange( - GetPlayerId(), MediaPlayerEfl::NetworkStateEmpty); + } + case GST_STATE_CHANGE_FAILURE: { + LOG(ERROR) << "Failure: State: " + << gst_element_state_get_name(state) + << " pending: " + << gst_element_state_get_name(pending); + HandleError(MediaPlayerEfl::NetworkStateDecodeError); break; - case GST_STATE_PAUSED: - case GST_STATE_PLAYING: - if (!is_file_url_) - StartBufferingUpdateTimer(); - - VLOG(1) << "state " << gst_element_state_get_name(state) - << " buffered_ " << buffered_ - << " is_file_url_ " << is_file_url_ - << " is_paused_ " << is_paused_ - << " is_seeking_ " << is_seeking_; - - if (buffered_ == 100 || is_file_url_) { - if (state == GST_STATE_PAUSED && !is_paused_) { - if (gst_element_set_state(gst_playbin_, GST_STATE_PLAYING) - == GST_STATE_CHANGE_FAILURE) - LOG(ERROR) << "GStreamer state change failed"; - } - - // FIXME: On rapid playback on PIANO Widget, there are instences - // when 'ASYNC-DONE' message is not received on replay. - if (is_seeking_ && state == GST_STATE_PLAYING) { - LOG(ERROR) << "PLAYING state changed on seek"; - UpdateSeekState(false); - main_loop_->PostTask(FROM_HERE, - base::Bind(&MediaPlayerBridgeGstreamer::OnTimeChanged, - base::Unretained(this))); - } + } + case GST_STATE_CHANGE_NO_PREROLL: { + if (state == GST_STATE_READY) { + manager()->OnReadyStateChange( + GetPlayerId(), MediaPlayerEfl::ReadyStateHaveNothing); + } else if (state == GST_STATE_PAUSED) { manager()->OnReadyStateChange( GetPlayerId(), MediaPlayerEfl::ReadyStateHaveEnoughData); - manager()->OnNetworkStateChange( - GetPlayerId(), MediaPlayerEfl::NetworkStateLoaded); - } else { - if (state == GST_STATE_PLAYING) { - if (gst_element_set_state(gst_playbin_, GST_STATE_PAUSED) - == GST_STATE_CHANGE_FAILURE) - LOG(ERROR) << "GStreamer state change failed"; - manager()->OnReadyStateChange( - GetPlayerId(), MediaPlayerEfl::ReadyStateHaveCurrentData); - manager()->OnNetworkStateChange( - GetPlayerId(), MediaPlayerEfl::NetworkStateLoading); - } + is_paused_ = true; + is_live_stream_ = true; + } else if (state == GST_STATE_PLAYING) { + is_paused_ = false; } + manager()->OnNetworkStateChange( + GetPlayerId(), MediaPlayerEfl::NetworkStateLoading); break; + } default: - LOG(ERROR) << "GStreamer unhandled state " - << gst_element_state_get_name(state); break; - } - break; - case GST_STATE_CHANGE_ASYNC: - // FIXME: For live stream. - break; - case GST_STATE_CHANGE_FAILURE: - LOG(ERROR) << "Failure: State: " - << gst_element_state_get_name(state) - << " pending: " - << gst_element_state_get_name(pending); - HandleError(MediaPlayerEfl::NetworkStateDecodeError); - break; - case GST_STATE_CHANGE_NO_PREROLL: - if (state == GST_STATE_READY) { - manager()->OnReadyStateChange( - GetPlayerId(), MediaPlayerEfl::ReadyStateHaveNothing); - } else if (state == GST_STATE_PAUSED) { - manager()->OnReadyStateChange( - GetPlayerId(), MediaPlayerEfl::ReadyStateHaveEnoughData); - is_paused_ = true; - is_live_stream_ = true; - } else if (state == GST_STATE_PLAYING) { - is_paused_ = false; - } - manager()->OnNetworkStateChange( - GetPlayerId(), MediaPlayerEfl::NetworkStateLoading); - break; - default: - LOG(ERROR) << "Unhandled return type: " << ret; - break; } } -void MediaPlayerBridgeGstreamer::FrameReady( - const scoped_refptr& frame) { -} - void MediaPlayerBridgeGstreamer::GetFrameDetails() { -#if GST_VERSION_MAJOR == 1 - GstSample* sample = gst_app_sink_pull_preroll(GST_APP_SINK(gst_appsink_)); + GstSample* sample = gst_app_sink_pull_preroll(GST_APP_SINK(appsink_)); if (!sample) return; - GstCaps* caps = gst_sample_get_caps(sample); - if (!caps) + if (!GetGstVideoBufferMetaData(sample, &width_, + &height_, &video_format_)) { + gst_sample_unref(sample); return; - - GstVideoInfo vi; - gst_video_info_from_caps(&vi, caps); - - gst_width_ = GST_VIDEO_INFO_WIDTH(&vi); - gst_height_ = GST_VIDEO_INFO_HEIGHT(&vi); - switch(GST_VIDEO_INFO_FORMAT(&vi)) { - case GST_VIDEO_FORMAT_I420:{ - video_format_ = GST_MAKE_FOURCC('I','4','2','0'); - break; - } - case GST_VIDEO_FORMAT_NV12:{ - video_format_ = GST_MAKE_FOURCC('N','V','1','2'); - break; - } - default: - LOG(ERROR) << "Unknown format : " << GST_VIDEO_INFO_FORMAT(&vi); - break; } -#else - GstBuffer* sample = gst_app_sink_pull_preroll(GST_APP_SINK(gst_appsink_)); - if (!sample) - return; - GstCaps* caps = gst_buffer_get_caps(GST_BUFFER(sample)); - if (!caps) - return; - - const GstStructure* str = gst_caps_get_structure(caps, 0); - gst_caps_unref(caps); - if (!str) - return; - - if (!gst_structure_get_int(str, "width", &gst_width_) || - !gst_structure_get_int(str, "height", &gst_height_) || - !gst_structure_get_fourcc(str, "format", &video_format_)) - LOG(ERROR) << "Pre-roll buffer info could not be obtained"; -#endif - - // Need to update frame details before sending sample. + // Need to update frame details before sending buffer. manager()->OnMediaDataChange( GetPlayerId(), static_cast(video_format_), - gst_height_, gst_width_, media_type_); - - if (video_format_ == GST_VIDEO_SN12) { - uint tile_w_align = ((gst_width_ - 1) / SN12_TILE_WIDTH + 2) & ~1; - bufsize_sn12_ = SN12_TILE_SIZE * tile_w_align * ((gst_height_ - 1) / - SN12_TILE_HEIGHT + 1) + (((gst_height_ + 1) & ~1) / 2) * tile_w_align * - SN12_TILE_WIDTH; - } + height_, width_, media_type_); SampleReady(sample); } -// FIXME: Works well for video playback. Do the same for /consider audio -// prerolling. void MediaPlayerBridgeGstreamer::PrerollComplete() { - if(!is_pixmap_used_) { - UpdateMediaType(); - if (media_type_ & MEDIA_VIDEO_MASK) - GetFrameDetails(); - else - manager()->OnMediaDataChange( - GetPlayerId(), static_cast(video_format_), - gst_height_, gst_width_, media_type_); - - VLOG(1) << "MediaPlayerBridgeGstreamer::PrerollComplete." - << " video_format " << video_format_ - << " width " << gst_width_ - << " height " << gst_height_ - << " media_type " << media_type_; - } else { - UpdateMediaType(); +#if !defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) + if (media_type_ & MEDIA_VIDEO_MASK) { + GetFrameDetails(); + } else +#endif + { + manager()->OnMediaDataChange( + GetPlayerId(), static_cast(video_format_), + height_, width_, media_type_); } - is_prerolled_ = true; + is_prerolled_ = true; } void MediaPlayerBridgeGstreamer::OnPlaybackComplete() { - VLOG(1) << "OnPlaybackComplete" << " ID " << GetPlayerId(); - is_end_reached_ = true; - -#if defined(OS_TIZEN_MOBILE) && (defined(TIZEN_V_2_3) || defined(TIZEN_V_2_4)) - if (device_power_release_lock(POWER_LOCK_DISPLAY) != DEVICE_ERROR_NONE) - LOG(ERROR) << "|device_power_release_lock| request failed"; +#if defined(OS_TIZEN_MOBILE) + ReleaseDisplayLock(); #endif + is_end_reached_ = true; StopCurrentTimeUpdateTimer(); manager()->OnTimeUpdate(GetPlayerId(), GetCurrentTime()); manager()->OnTimeChanged(GetPlayerId()); @@ -1119,82 +923,44 @@ void MediaPlayerBridgeGstreamer::UpdateSeekState(bool state) { } void MediaPlayerBridgeGstreamer::OnTimeChanged() { - VLOG(1) << __FUNCTION__ << " : Player Id = " << GetPlayerId(); DCHECK(main_loop_->BelongsToCurrentThread()); manager()->OnTimeChanged(GetPlayerId()); } void MediaPlayerBridgeGstreamer::OnUpdateStates() { - VLOG(1) << __FUNCTION__ << " : Player Id = " << GetPlayerId(); DCHECK(main_loop_->BelongsToCurrentThread()); UpdateStates(); } GstElement* MediaPlayerBridgeGstreamer::GetVideoSink() { #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) - is_pixmap_used_ = true; return gst_element_factory_make("xvimagesink", kVideoSink); #else - is_pixmap_used_ = false; return gst_element_factory_make("appsink", kVideoSink); #endif } void MediaPlayerBridgeGstreamer::PrepareForVideoFrame() { - VLOG(1) << "MediaElement using shared memory to pass the frames"; - int flags = 0; - g_object_get(gst_playbin_, "flags", &flags, NULL); - flags = GST_PLAY_FLAG_NATIVE_VIDEO | GST_PLAY_FLAG_NATIVE_AUDIO - | GST_PLAY_FLAG_DOWNLOAD; -#ifdef OS_TIZEN_TV - flags |= GST_PLAY_FLAG_NATIVE_VIDEO | GST_PLAY_FLAG_NATIVE_AUDIO; - flags &= ~GST_PLAY_FLAG_VIDEO & ~GST_PLAY_FLAG_AUDIO & - ~GST_PLAY_FLAG_DEINTERLACE & ~GST_PLAY_FLAG_SOFT_COLORBALANCE; -#if defined(TIZEN_V_3_0) - flags |= GST_PLAY_FLAG_VIDEO | GST_PLAY_FLAG_AUDIO | GST_PLAY_FLAG_NATIVE_VIDEO; - flags &= ~GST_PLAY_FLAG_NATIVE_AUDIO; -#endif -#endif - g_object_set(gst_playbin_, "flags", flags, NULL); -#if GST_VERSION_MAJOR == 1 - GstAppSinkCallbacks callbacks = {on_gst_appsink_eos, on_gst_appsink_preroll, - on_gst_appsink_sample}; -#else - GstAppSinkCallbacks callbacks = {on_gst_appsink_eos, - on_gst_appsink_preroll, - on_gst_appsink_sample, - NULL, - {NULL, NULL, NULL}}; -#endif - gst_app_sink_set_callbacks(GST_APP_SINK(gst_appsink_), &callbacks, - this, NULL); - - g_object_set(G_OBJECT(gst_playbin_), kPropertyBufferSize, - kPreloadBufferSize, NULL); - g_object_set(G_OBJECT(gst_appsink_), kPropertyMaxBuffers, - (guint)kMaxBuffer, NULL); + GstAppSinkCallbacks callbacks = {NULL, OnGstAppsinkPrerollCB, + OnGstAppsinkSampleCB, NULL}; + gst_app_sink_set_callbacks(GST_APP_SINK(appsink_), &callbacks, + this, NULL); } #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) void MediaPlayerBridgeGstreamer::PrepareForVideoSink() { - VLOG(1) << "MediaElement Backed by Video-Sink (xvimagesink)"; int flags = 0; - g_object_get(gst_playbin_, "flags", &flags, NULL); + g_object_get(pipeline_, "flags", &flags, NULL); flags |= GST_PLAY_FLAG_NATIVE_VIDEO; flags &= ~GST_PLAY_FLAG_TEXT; - g_object_set(gst_playbin_, "flags", flags, NULL); + g_object_set(pipeline_, "flags", flags, NULL); } void MediaPlayerBridgeGstreamer::XWindowIdPrepared(GstMessage* message) { // It is called just once after video src is set. -#if GST_VERSION_MAJOR == 1 const GstStructure* structure = gst_message_get_structure(message); - gst_structure_get_int(structure, "video-width", &gst_width_); - gst_structure_get_int(structure, "video-height", &gst_height_); -#else - gst_structure_get_int(message->structure, "video-width", &gst_width_); - gst_structure_get_int(message->structure, "video-height", &gst_height_); -#endif + gst_structure_get_int(structure, "video-width", &width_); + gst_structure_get_int(structure, "video-height", &height_); SetPixmap(); } @@ -1203,50 +969,109 @@ int MediaPlayerBridgeGstreamer::GetSurfaceID() const { } void MediaPlayerBridgeGstreamer::SetPixmap() { - efl_pixmap_ = gfx::EflPixmap::Create(gfx::EflPixmap::SURFACE, gfx::Size( - gst_width_, gst_height_)); + efl_pixmap_ = gfx::EflPixmap::Create(gfx::EflPixmap::SURFACE, + gfx::Size(width_, height_)); + if (!efl_pixmap_.get()) { LOG(ERROR) << "gfx::EflPixmap::Create() failed to create Pixmap"; - return ; + return; } + pixmap_id_ = efl_pixmap_->GetId(); - g_object_set (gst_appsink_, "pixmap-id-callback", get_pixmap_id_cb, NULL); - g_object_set (gst_appsink_, "pixmap-id-callback-userdata", this, NULL); - - //Register to get notification from ecore for damage updates. - m_damage = ecore_x_damage_new( - pixmap_id_, ECORE_X_DAMAGE_REPORT_RAW_RECTANGLES); - m_damageHandler = ecore_event_handler_add( - ECORE_X_EVENT_DAMAGE_NOTIFY, notify_damage_updated_cb, this); - g_object_set(gst_appsink_, "rotate", DEGREE_0, NULL); - - // Passing NUL value for video_format. Its not required but - // |webmediaplayertizen| expects a value. - UpdateMediaType(); - manager()->OnMediaDataChange( - GetPlayerId(), video_format_, gst_height_, gst_width_, media_type_); +#if defined(OS_TIZEN_TV) + g_object_set(appsink_, "pixmap-id-callback", GetPixmapIdCB, NULL); + g_object_set(appsink_, "pixmap-id-callback-userdata", this, NULL); +#else + gst_x_overlay_set_window_handle(GST_X_OVERLAY(appsink_), pixmap_id_); +#endif + + // Register to get notification from ecore for damage updates. + m_damage_ = ecore_x_damage_new(pixmap_id_, + ECORE_X_DAMAGE_REPORT_RAW_RECTANGLES); + m_damage_handler_ = ecore_event_handler_add(ECORE_X_EVENT_DAMAGE_NOTIFY, + NotifyDamageUpdatedCB, this); + g_object_set(appsink_, "rotate", DEGREE_0, NULL); + + PrerollComplete(); } void MediaPlayerBridgeGstreamer::PlatformSurfaceUpdated() { gint64 current_time = 0; GstFormat format = GST_FORMAT_TIME; -#if GST_VERSION_MAJOR == 1 - gst_element_query_position(gst_playbin_, format, ¤t_time); -#else - gst_element_query_position(gst_playbin_, &format, ¤t_time); -#endif + gst_element_query_position(pipeline_, format, ¤t_time); base::TimeDelta timestamp = base::TimeDelta::FromMicroseconds( current_time / base::Time::kNanosecondsPerMicrosecond); manager()->OnPlatformSurfaceUpdated(GetPlayerId(), pixmap_id_, timestamp); } #endif +void MediaPlayerBridgeGstreamer::OnNewPadAdded(GstPad* new_pad) { + GstCaps* new_pad_caps = gst_pad_query_caps(new_pad, NULL); + const gchar* new_pad_type = + gst_structure_get_name(gst_caps_get_structure(new_pad_caps, 0)); + + if (g_str_has_prefix(new_pad_type, "audio/x-raw") && + !gst_pad_is_linked(audio_sinkpad_)) { + if (!gst_element_link_many(audio_convert_, audio_volume_, audio_sink_, + NULL)) { + LOG(ERROR) << "Could not link Audio Pipeline"; + HandleError(MediaPlayerEfl::NetworkStateDecodeError); + Release(); + } else { + media_type_ |= MEDIA_AUDIO_MASK; + gst_pad_link(new_pad, audio_sinkpad_); + } + } else if (g_str_has_prefix(new_pad_type, "video/x-raw") && + !gst_pad_is_linked(video_sinkpad_)) { +#if defined(TIZEN_MULTIMEDIA_USE_HW_CODEC) + if (!gst_element_link_filtered(video_convert_, appsink_, + gst_caps_new_simple("video/x-raw", "format", + G_TYPE_STRING, "I420", + NULL))) { + LOG(ERROR) << "Could not link Video Pipeline"; + HandleError(MediaPlayerEfl::NetworkStateDecodeError); + Release(); + } else +#endif + { + media_type_ |= MEDIA_VIDEO_MASK; + gst_pad_link(new_pad, video_sinkpad_); + } + } + gst_caps_unref(new_pad_caps); + new_pad_caps = NULL; +} + +void MediaPlayerBridgeGstreamer::OnNoMorePadsAvailable() { + if ((media_type_ & MEDIA_VIDEO_MASK) == 0) { + gst_element_set_state(appsink_, GST_STATE_NULL); +#if defined(TIZEN_MULTIMEDIA_USE_HW_CODEC) + gst_element_set_state(video_convert_, GST_STATE_NULL); + gst_bin_remove_many(GST_BIN(pipeline_), video_convert_, + appsink_, NULL); + GST_OBJECT_UNREF(video_convert_); +#else + gst_bin_remove(GST_BIN(pipeline_), appsink_); +#endif + GST_OBJECT_UNREF(appsink_); + } + if ((media_type_ & MEDIA_AUDIO_MASK) == 0) { + gst_element_set_state(audio_convert_, GST_STATE_NULL); + gst_element_set_state(audio_volume_, GST_STATE_NULL); + gst_element_set_state(audio_sink_, GST_STATE_NULL); + gst_bin_remove_many(GST_BIN(pipeline_), audio_convert_, audio_volume_, + audio_sink_, NULL); + GST_OBJECT_UNREF(audio_convert_); + GST_OBJECT_UNREF(audio_volume_); + GST_OBJECT_UNREF(audio_sink_); + } +} + void MediaPlayerBridgeGstreamer::HandleError( media::MediaPlayerEfl::NetworkState state) { LOG(ERROR) << "Error in MediaPlayerBridgeGstreamer::HandleError"; -#if defined(OS_TIZEN_MOBILE) && (defined(TIZEN_V_2_3) || defined(TIZEN_V_2_4)) - if (device_power_release_lock(POWER_LOCK_DISPLAY) != DEVICE_ERROR_NONE) - LOG(ERROR) << "|device_power_release_lock| request failed"; +#if defined(OS_TIZEN_MOBILE) + ReleaseDisplayLock(); #endif error_occured_ = true; diff --git a/tizen_src/chromium_impl/media/base/efl/media_player_bridge_gstreamer.h b/tizen_src/chromium_impl/media/base/efl/media_player_bridge_gstreamer.h index 64826b1..4724eec 100644 --- a/tizen_src/chromium_impl/media/base/efl/media_player_bridge_gstreamer.h +++ b/tizen_src/chromium_impl/media/base/efl/media_player_bridge_gstreamer.h @@ -2,18 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef MEDIA_TIZEN_MEDIA_PLAYER_BRIDGE_GSTREMEAR_H_ -#define MEDIA_TIZEN_MEDIA_PLAYER_BRIDGE_GSTREMEAR_H_ +#ifndef MEDIA_EFL_MEDIA_PLAYER_BRIDGE_GSTREMEAR_H_ +#define MEDIA_EFL_MEDIA_PLAYER_BRIDGE_GSTREMEAR_H_ #include #include #include -#if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) -#include -#include -#endif - #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/timer/timer.h" @@ -24,6 +19,9 @@ #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) #include "ui/gl/efl_pixmap.h" + +#include +#include #endif namespace media { @@ -36,29 +34,23 @@ class MEDIA_EXPORT MediaPlayerBridgeGstreamer const GURL& url, double volume, MediaPlayerManager* manager); - virtual ~MediaPlayerBridgeGstreamer(); + ~MediaPlayerBridgeGstreamer() override {} // MediaPlayerEfl implementation. - virtual void Play() override; - virtual void Pause(bool is_media_related_action) override; - virtual void SetRate(double rate) override; - virtual void Seek(const double time) override; - virtual void SetVolume(double volume) override; - virtual double GetCurrentTime() override; - virtual void Destroy() override; + void Play() override; + void Pause(bool is_media_related_action) override; + void SetRate(double rate) override; + void Seek(const double time) override; + void SetVolume(double volume) override; + double GetCurrentTime() override; + void Destroy() override; // Error handling API void HandleError(media::MediaPlayerEfl::NetworkState state); void HandleMessage(GstMessage* message); - void HandlePluginInstallerResult(GstInstallPluginsReturn result); -#if GST_VERSION_MAJOR == 1 GstSample* PullSample(); void SampleReady(GstSample* buffer); -#else - GstBuffer* PullSample(); - void SampleReady(const GstBuffer* buffer); -#endif void PrerollComplete(); #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) @@ -66,7 +58,11 @@ class MEDIA_EXPORT MediaPlayerBridgeGstreamer int GetSurfaceID() const; #endif + void OnNewPadAdded(GstPad* pad); + void OnNoMorePadsAvailable(); + protected: + bool InitPipeline(); void Release() override; private: @@ -83,13 +79,11 @@ class MEDIA_EXPORT MediaPlayerBridgeGstreamer void UpdateStates(); void OnUpdateStates(); void UpdateDuration(); - void UpdateMediaType(); void UpdateSeekState(bool state); void OnPlaybackComplete(); void OnTimeChanged(); - void FrameReady(const scoped_refptr& frame); void GetFrameDetails(); void ProcessBufferingStats(GstMessage* message); void GetBufferedTimeRanges(); @@ -100,19 +94,28 @@ class MEDIA_EXPORT MediaPlayerBridgeGstreamer #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) void PrepareForVideoSink(); - void XWindowIdPrepared(GstMessage*); - bool IsXWindowHadleSet(){return pixmap_id_ ? true : false ;} + void XWindowIdPrepared(GstMessage* message); + bool IsXWindowHandleSet() {return pixmap_id_ ? true : false ;} void SetPixmap(); #endif private: const scoped_refptr main_loop_; - GstElement* gst_playbin_; - GstElement* gst_appsink_; + GstElement* pipeline_; + GstElement* appsink_; + GstElement* uridecodebinsrc_; +#if defined(TIZEN_MULTIMEDIA_USE_HW_CODEC) + GstElement* video_convert_; +#endif + GstElement* audio_convert_; + GstElement* audio_volume_; + GstElement* audio_sink_; + GstPad* audio_sinkpad_; + GstPad* video_sinkpad_; + GURL url_; - double volume_; - gint gst_width_; - gint gst_height_; + gint width_; + gint height_; bool is_prerolled_; bool is_paused_; @@ -124,26 +127,18 @@ class MEDIA_EXPORT MediaPlayerBridgeGstreamer int media_type_; bool is_live_stream_; bool is_file_url_; - bool is_end_reached_ ; - bool is_seeking_ ; - bool is_seek_pending_ ; + bool is_end_reached_; + bool is_seeking_; double seek_duration_; - bool error_occured_; - bool missing_plugins_; - bool is_pixmap_used_; - #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) int pixmap_id_; scoped_refptr efl_pixmap_; - Ecore_X_Damage m_damage; - Ecore_Event_Handler* m_damageHandler; + Ecore_X_Damage m_damage_; + Ecore_Event_Handler* m_damage_handler_; #endif - uint bufsize_sn12_; - base::SharedMemory shared_memory; - uint32 shared_memory_size; - base::SharedMemoryHandle foreign_memory_handle; + bool error_occured_; base::RepeatingTimer current_time_update_timer_; base::RepeatingTimer buffering_update_timer_; @@ -153,4 +148,4 @@ class MEDIA_EXPORT MediaPlayerBridgeGstreamer } // namespace media -#endif // MEDIA_TIZEN_MEDIA_PLAYER_BRIDGE_GSTREMEAR_H_ +#endif // MEDIA_EFL_MEDIA_PLAYER_BRIDGE_GSTREMEAR_H_ diff --git a/tizen_src/chromium_impl/media/base/efl/media_player_efl.h b/tizen_src/chromium_impl/media/base/efl/media_player_efl.h index c57dc3b..5cd544e 100644 --- a/tizen_src/chromium_impl/media/base/efl/media_player_efl.h +++ b/tizen_src/chromium_impl/media/base/efl/media_player_efl.h @@ -2,15 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef MEDIA_TIZEN_MEDIA_PLAYER_TIZEN_H_ -#define MEDIA_TIZEN_MEDIA_PLAYER_TIZEN_H_ +#ifndef MEDIA_BASE_EFL_MEDIA_PLAYER_EFL_H_ +#define MEDIA_BASE_EFL_MEDIA_PLAYER_EFL_H_ #include #include "base/basictypes.h" #include "base/callback.h" #include "base/time/time.h" -#include "content/common/media/efl/media_player_messages_enums_efl.h" #include "media/base/media_export.h" #include "url/gurl.h" @@ -30,9 +29,9 @@ enum MediaErrorType { const int MEDIA_AUDIO_MASK = 0x02; const int MEDIA_VIDEO_MASK = 0x01; -class MEDIA_EXPORT MediaPlayerEfl{ +class MEDIA_EXPORT MediaPlayerEfl { public: - // FIXME: Remove these enum and use webkit's + // Should be same as webkit's enum ReadyState { ReadyStateHaveNothing, ReadyStateHaveMetadata, @@ -56,8 +55,7 @@ class MEDIA_EXPORT MediaPlayerEfl{ int64 end; } TimeRanges; - MediaPlayerEfl() { } - virtual ~MediaPlayerEfl() { } + virtual ~MediaPlayerEfl() {} // Start playing the media. virtual void Play() = 0; @@ -90,8 +88,8 @@ class MEDIA_EXPORT MediaPlayerEfl{ // Release the player resources. virtual void Release() = 0; - MediaPlayerEfl(int player_id, MediaPlayerManager* manager) - : destructing_(false), player_id_(player_id), manager_(manager) { } + explicit MediaPlayerEfl(int player_id, MediaPlayerManager* manager) + : destructing_(false), player_id_(player_id), manager_(manager) {} MediaPlayerManager* manager() { return manager_; } @@ -109,4 +107,4 @@ class MEDIA_EXPORT MediaPlayerEfl{ } // namespace media -#endif // MEDIA_TIZEN_MEDIA_PLAYER_TIZEN_H_ +#endif // MEDIA_BASE_EFL_MEDIA_PLAYER_EFL_H_ \ No newline at end of file diff --git a/tizen_src/chromium_impl/media/base/efl/media_player_manager_efl.h b/tizen_src/chromium_impl/media/base/efl/media_player_manager_efl.h index 7102fee..b685ae2 100644 --- a/tizen_src/chromium_impl/media/base/efl/media_player_manager_efl.h +++ b/tizen_src/chromium_impl/media/base/efl/media_player_manager_efl.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef MEDIA_BASE_TIZEN_MEDIA_PLAYER_TIZEN_MANAGER_H_ -#define MEDIA_BASE_TIZEN_MEDIA_PLAYER_TIZEN_MANAGER_H_ +#ifndef MEDIA_BASE_EFL_MEDIA_PLAYER_MANAGER_EFL_H_ +#define MEDIA_BASE_EFL_MEDIA_PLAYER_MANAGER_EFL_H_ #include @@ -16,13 +16,12 @@ class MediaPlayerEfl; class MEDIA_EXPORT MediaPlayerManager { public: - virtual ~MediaPlayerManager() { } + virtual ~MediaPlayerManager() {} virtual MediaPlayerEfl* GetPlayer(int player_id) = 0; virtual void OnTimeChanged(int player_id) = 0; virtual void OnTimeUpdate(int player_id, double current_time) = 0; virtual void OnRequestSeek(int player_id, double seek_time) = 0; - virtual void OnPauseStateChange(int player_id, bool state) = 0; virtual void OnSeekStateChange(int player_id, bool state) = 0; virtual void OnBufferUpdate( int player_id, @@ -33,25 +32,19 @@ class MEDIA_EXPORT MediaPlayerManager { virtual void OnNetworkStateChange( int player_id, MediaPlayerEfl::NetworkState state) = 0; - virtual void OnMediaDataChange( - int player_id, - int format, - int height, - int width, - int media) = 0; + virtual void OnMediaDataChange(int player_id, int format, int height, + int width, int media) = 0; virtual void OnNewFrameAvailable( int player_id, base::SharedMemoryHandle handle, uint32 length, base::TimeDelta timestamp) = 0; #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) - virtual void OnPlatformSurfaceUpdated( - int player_id, - int pixmap_id, - base::TimeDelta timestamp) = 0; + virtual void OnPlatformSurfaceUpdated(int player_id, int pixmap_id, + base::TimeDelta timestamp) = 0; #endif }; } // namespace media -#endif // MEDIA_BASE_TIZEN_MEDIA_PLAYER_TIZEN_MANAGER_H_ +#endif // MEDIA_BASE_EFL_MEDIA_PLAYER_MANAGER_EFL_H_ \ No newline at end of file diff --git a/tizen_src/chromium_impl/media/base/efl/media_player_util_efl.cc b/tizen_src/chromium_impl/media/base/efl/media_player_util_efl.cc new file mode 100644 index 0000000..d6a5730 --- /dev/null +++ b/tizen_src/chromium_impl/media/base/efl/media_player_util_efl.cc @@ -0,0 +1,116 @@ +// Copyright 2014 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. + +#include "media/base/efl/media_player_util_efl.h" + +#include "base/logging.h" +#include "base/time/time.h" + +#if defined(OS_TIZEN_MOBILE) +#include +#endif + +namespace media { + +GstClockTime ConvertToGstClockTime(double time) { + if (time < 0) { + LOG(ERROR) << "Invalid time:" << time << " Reset to 0"; + time = 0; + } + + // Extract the integer part of the time (seconds) and the fractional part + // (microseconds). Attempt to round the microseconds so no floating point + // precision is lost and we can perform an accurate seek. + double seconds = 0; + double microSeconds = std::modf(time, &seconds) * 1000000; + GTimeVal timeValue; + timeValue.tv_sec = static_cast(seconds); + timeValue.tv_usec = static_cast(lround(microSeconds / 10) * 10); + return GST_TIMEVAL_TO_TIME(timeValue); +} + +double ConvertNanoSecondsToSeconds(int64 time) { + return base::TimeDelta::FromMicroseconds( + time / + base::Time::kNanosecondsPerMicrosecond).InSecondsF(); +} + +double ConvertMilliSecondsToSeconds(int time) { + return base::TimeDelta::FromMilliseconds(time).InSecondsF(); +} + +double ConvertSecondsToMilliSeconds(double time) { + if (time < 0) { + LOG(ERROR) << "Invalid time:" << time << " Reset to 0"; + time = 0; + } + + return base::TimeDelta::FromSecondsD(time).InMillisecondsF(); +} + +GURL GetCleanURL(std::string url) { + // FIXME: Need to consider "app://" scheme. + CHECK(url.compare(0, 6, "app://")); + if (!url.compare(0, 7, "file://")) { + int position = url.find("?"); + if (position != -1) + url.erase(url.begin() + position, url.end()); + } + GURL url_(url); + return url_; +} + +int GetSN12BufferSize(int video_width, int video_height) { + uint tile_w_align = ((video_width - 1) / SN12_TILE_WIDTH + 2) & ~1; + return (SN12_TILE_SIZE * tile_w_align * + ((video_height - 1) / SN12_TILE_HEIGHT + 1) + + (((video_height + 1) & ~1) / 2) * tile_w_align * SN12_TILE_WIDTH); +} + +bool GetGstVideoBufferMetaData(GstSample* sample, + gint* video_width, + gint* video_height, + guint32* video_format) { + GstCaps* caps = gst_sample_get_caps(sample); + if (!caps) + return false; + + GstVideoInfo vi; + gst_video_info_from_caps(&vi, caps); + + *video_width = GST_VIDEO_INFO_WIDTH(&vi); + *video_height = GST_VIDEO_INFO_HEIGHT(&vi); + if (video_format) { + switch(GST_VIDEO_INFO_FORMAT(&vi)) { + case GST_VIDEO_FORMAT_I420: { + *video_format = GST_MAKE_FOURCC('I','4','2','0'); + break; + } + case GST_VIDEO_FORMAT_NV12: { + *video_format = GST_MAKE_FOURCC('N','V','1','2'); + break; + } + default: + LOG(ERROR) << "Unknown format : " << GST_VIDEO_INFO_FORMAT(&vi); + break; + } + } + return true; +} + +#if defined(OS_TIZEN_MOBILE) +void WakeUpDisplayAndAcquireDisplayLock() { + if (device_power_wakeup(false) != DEVICE_ERROR_NONE) + LOG(ERROR) << "|device_power_wakeup| request failed"; + if (device_power_request_lock(POWER_LOCK_DISPLAY, 0) != DEVICE_ERROR_NONE) + LOG(ERROR) << "|device_power_request_lock| request failed"; +} + +void ReleaseDisplayLock() { + if (device_power_release_lock(POWER_LOCK_DISPLAY) != DEVICE_ERROR_NONE) + LOG(ERROR) << "|device_power_release_lock| request failed"; +} +#endif + +} // namespace media diff --git a/tizen_src/chromium_impl/media/base/efl/media_player_util_efl.h b/tizen_src/chromium_impl/media/base/efl/media_player_util_efl.h new file mode 100644 index 0000000..feab96a --- /dev/null +++ b/tizen_src/chromium_impl/media/base/efl/media_player_util_efl.h @@ -0,0 +1,76 @@ +// Copyright 2014 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 MEDIA_BASE_EFL_MEDIA_PLAYER_UTIL_EFL_H_ +#define MEDIA_BASE_EFL_MEDIA_PLAYER_UTIL_EFL_H_ + +#include +#include + +#include "base/basictypes.h" +#include "url/gurl.h" + +namespace media { + +// Fourcc for gst-video-format. +const uint32 GST_VIDEO_SN12 = GST_MAKE_FOURCC('S', 'N', '1', '2'); +const uint32 GST_VIDEO_I420 = GST_MAKE_FOURCC('I', '4', '2', '0'); +const uint32 GST_VIDEO_NV12 = GST_MAKE_FOURCC('N', 'V', '1', '2'); + +// Tile size for SN12. +const uint SN12_TILE_WIDTH = 64; +const uint SN12_TILE_HEIGHT = 32; +const uint SN12_TILE_SIZE = SN12_TILE_WIDTH * SN12_TILE_HEIGHT; + +// GstPlayFlags in |gstplay-enum.h|. +typedef enum { + GST_PLAY_FLAG_VIDEO = (1 << 0), + GST_PLAY_FLAG_AUDIO = (1 << 1), + GST_PLAY_FLAG_TEXT = (1 << 2), + GST_PLAY_FLAG_VIS = (1 << 3), + GST_PLAY_FLAG_SOFT_VOLUME = (1 << 4), + GST_PLAY_FLAG_NATIVE_AUDIO = (1 << 5), + GST_PLAY_FLAG_NATIVE_VIDEO = (1 << 6), + GST_PLAY_FLAG_DOWNLOAD = (1 << 7), + GST_PLAY_FLAG_BUFFERING = (1 << 8), + GST_PLAY_FLAG_DEINTERLACE = (1 << 9), + GST_PLAY_FLAG_SOFT_COLORBALANCE = (1 << 10) +} GstPlayFlags; + +#if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) +typedef enum { + DEGREE_0, // No rotate. + DEGREE_90, // Rotate 90 degree count clockwise. + DEGREE_180, // Rotate 180 degree count clockwise. + DEGREE_270 // Rotate 270 degree count clockwise. +} RotateAngle; +#endif + +typedef enum { + GST_AUTOPLUG_SELECT_TRY, + GST_AUTOPLUG_SELECT_EXPOSE, + GST_AUTOPLUG_SELECT_SKIP +} GstAutoplugSelectResult; + +GstClockTime ConvertToGstClockTime(double time); +double ConvertNanoSecondsToSeconds(int64 time); +double ConvertMilliSecondsToSeconds(int time); +double ConvertSecondsToMilliSeconds(double time); + +// Removes query string from URI. +GURL GetCleanURL(std::string url); +int GetSN12BufferSize(int video_width, int video_height); +bool GetGstVideoBufferMetaData(GstSample* sample, + gint* video_width, + gint* video_height, + guint32* video_format); + +#if defined(OS_TIZEN_MOBILE) +void WakeUpDisplayAndAcquireDisplayLock(); +void ReleaseDisplayLock(); +#endif + +} // namespace media + +#endif // MEDIA_BASE_EFL_MEDIA_PLAYER_UTIL_EFL_H_ diff --git a/tizen_src/chromium_impl/media/base/efl/media_source_player_gstreamer.cc b/tizen_src/chromium_impl/media/base/efl/media_source_player_gstreamer.cc index 6bbfe30..9d19e95 100644 --- a/tizen_src/chromium_impl/media/base/efl/media_source_player_gstreamer.cc +++ b/tizen_src/chromium_impl/media/base/efl/media_source_player_gstreamer.cc @@ -7,30 +7,14 @@ #include #include #include +#include #include "base/process/process.h" #include "media/base/efl/media_player_manager_efl.h" - -#if defined(OS_TIZEN_MOBILE) && (defined(TIZEN_V_2_3) || defined(TIZEN_V_2_4)) -#include -#endif - -#if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) -#if GST_VERSION_MAJOR == 1 -#include -#else -#include -#endif -#endif +#include "media/base/efl/media_player_util_efl.h" namespace { -const uint32 GST_VIDEO_SN12 = GST_MAKE_FOURCC('S','N','1','2'); - -const uint SN12_TILE_WIDTH = 64; -const uint SN12_TILE_HEIGHT = 32; -const uint SN12_TILE_SIZE = SN12_TILE_WIDTH * SN12_TILE_HEIGHT; - // Pipeline element name const char* kPipelineName = "gst_pipeline"; @@ -41,52 +25,32 @@ const int kDurationUpdateInterval = 100; // Reason to choose kSixteenMilliSeconds is duration of each video frame at // 60 fps video will be ~16 milliseconds. const int64 kSixteenMilliSeconds = 16000000; +const int kMaxBufPercent = 100; -const char *h264elements[] = { - "h264parse" -#if defined(OS_TIZEN_MOBILE) - , "avdec_h264" -#elif defined(OS_TIZEN_TV) -#if defined(TIZEN_V_3_0) - , "avdec_h264" -#else - , "omx_h264dec" -#endif +const int kBytesPerMegabyte = 1048576; + +const char* h264elements[] = { + "h264parse", +#if defined(TIZEN_MULTIMEDIA_USE_HW_CODEC) + "omx_h264dec", #else - , "ffdec_h264" + "avdec_h264" #endif }; -const char *aacelements[] = { - "aacparse" -#if defined(OS_TIZEN_MOBILE) - , "avdec_aac", "autoaudiosink" -#elif defined(OS_TIZEN_TV) -#if defined(TIZEN_V_3_0) - , "avdec_aac", "alsasink" -#else - , "omx_aacdec", "alsasink" -#endif +const char* aacelements[] = { + "aacparse", +#if defined(TIZEN_MULTIMEDIA_USE_HW_CODEC) + "omx_aacdec", "alsasink", #else - , "faad", "autoaudiosink" + "avdec_aac", "alsasink" #endif }; -// FIXME: This is derived from command-line pipeline on desktop and mobile. -// Need to find the pipeline on TV. -// Also the connection might be different when converting it to code. -const char *mp3elements[] = { - "mpegaudioparse" -#if defined(OS_TIZEN_MOBILE) - , "avdec_mp3" -#else -#if defined(TIZEN_V_3_0) - , "avdec_mp3" -#else - , "ffdec_mp3" -#endif -#endif - ,"autoaudiosink" +const char* mp3elements[] = { + "mpegaudioparse", + "avdec_mp3", + "autoaudiosink" }; const AudioCodecGstElementsMapping AudioMapping[] = { @@ -100,34 +64,18 @@ const VideoCodecGstElementsMapping VideoMapping[] = { {media::kUnknownVideoCodec, NULL} }; -GstClockTime ConvertToGstClockTime(double time) { - if (time < 0) { - LOG(ERROR) << "Invalid time:" << time << " Reset to 0"; - time = 0; - } - - // Extract the integer part of the time (seconds) and the fractional part - // (microseconds). Attempt to round the microseconds so no floating point - // precision is lost and we can perform an accurate seek. - double seconds; - double microSeconds = std::modf(time, &seconds) * 1000000; - GTimeVal timeValue; - timeValue.tv_sec = static_cast(seconds); - timeValue.tv_usec = static_cast(lround(microSeconds / 10) * 10); - return GST_TIMEVAL_TO_TIME(timeValue); -} - -double ConvertNanoSecondsToSeconds(int64 time) { - double seconds = static_cast(time) / - (base::Time::kNanosecondsPerSecond); - return seconds; +#if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) +// Generating Unique integer for given height / width. +int GetUniqueKey(int x, int y) { + return ((x << 16) | y); } +#endif } // namespace namespace media { -static GstBusSyncReply gst_pipeline_message_cb( +static GstBusSyncReply GstPipelineMessageCB( GstBus* bus, GstMessage* message, gpointer user_data) { @@ -142,7 +90,7 @@ static GstBusSyncReply gst_pipeline_message_cb( } #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) -static Eina_Bool notify_damage_updated_cb( +static Eina_Bool NotifyDamageUpdatedCB( void* user_data, int type, void* event) { @@ -153,88 +101,29 @@ static Eina_Bool notify_damage_updated_cb( player->PlatformSurfaceUpdated(); return ECORE_CALLBACK_PASS_ON; } -#endif -#if defined(OS_TIZEN_TV) && !defined(TIZEN_V_3_0) -#if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) -static int get_pixmap_id_cb(void* user_data) { +#if defined(OS_TIZEN_TV) +static int GetPixmapIdCB(void* user_data) { MediaSourcePlayerGstreamer* player = static_cast(user_data); return player->GetSurfaceID(); } #endif - -static ASM_cb_result_t media_player_audio_session_event_source_pause( - ASM_event_sources_t event_source, - void* user_data) { - MediaPlayerEfl* player = - static_cast(user_data); - if (!player) { - return ASM_CB_RES_IGNORE; - } - - switch (event_source) { - case ASM_EVENT_SOURCE_CALL_START: - case ASM_EVENT_SOURCE_ALARM_START: - case ASM_EVENT_SOURCE_MEDIA: - case ASM_EVENT_SOURCE_EMERGENCY_START: - case ASM_EVENT_SOURCE_OTHER_PLAYER_APP: - case ASM_EVENT_SOURCE_RESOURCE_CONFLICT: - case ASM_EVENT_SOURCE_EARJACK_UNPLUG: - player->Pause(true); - return ASM_CB_RES_PAUSE; - default: - return ASM_CB_RES_NONE; - } -} - -static ASM_cb_result_t media_player_audio_session_event_source_play( - ASM_event_sources_t event_source, - void* user_data) { - MediaPlayerEfl* player = - static_cast(user_data); - if (!player) { - return ASM_CB_RES_IGNORE; - } - - switch (event_source) { - case ASM_EVENT_SOURCE_ALARM_END: - player->Play(); - return ASM_CB_RES_PLAYING; - default: - return ASM_CB_RES_NONE; - } -} - -static ASM_cb_result_t media_player_private_audio_session_notify_cb( - int, - ASM_event_sources_t event_source, - ASM_sound_commands_t command, - unsigned int, - void* user_data) { - if (command == ASM_COMMAND_STOP || command == ASM_COMMAND_PAUSE) - return media_player_audio_session_event_source_pause( - event_source, user_data); - if (command == ASM_COMMAND_PLAY || command == ASM_COMMAND_RESUME) - return media_player_audio_session_event_source_play( - event_source, user_data); - return ASM_CB_RES_NONE; -} #endif -static void on_gst_start_video_feed_cb( +static void OnGstStartVideoFeedCB( GstAppSrc* pipeline, guint size, - void *user_data) { + void* user_data) { MediaSourcePlayerGstreamer* player = static_cast(user_data); if (!player || player->IsPlayerDestructing()) return; player->OnReadDemuxedData(media::DemuxerStream::VIDEO); - return ; + return; } -static void on_gst_stop_video_feed_cb(GstAppSrc * pipeline,void *user_data) { +static void OnGstStopVideoFeedCB(GstAppSrc* pipeline, void* user_data) { MediaSourcePlayerGstreamer* player = static_cast(user_data); if (!player || player->IsPlayerDestructing()) @@ -242,10 +131,10 @@ static void on_gst_stop_video_feed_cb(GstAppSrc * pipeline,void *user_data) { player->OnStopDemuxedData(media::DemuxerStream::VIDEO); } -static gboolean on_gst_seek_video_feed_cb( +static gboolean OnGstSeekVideoFeedCB( GstAppSrc* pipeline, guint64 offset, - void *user_data) { + void* user_data) { MediaSourcePlayerGstreamer* player = static_cast(user_data); @@ -255,7 +144,7 @@ static gboolean on_gst_seek_video_feed_cb( return TRUE; } -static GstFlowReturn on_gst_appsink_preroll( +static GstFlowReturn OnGstAppsinkPreroll( GstAppSink* sink, gpointer user_data) { MediaSourcePlayerGstreamer* player = @@ -266,9 +155,7 @@ static GstFlowReturn on_gst_appsink_preroll( return GST_FLOW_OK; } -static GstFlowReturn on_gst_appsink_sample( - GstAppSink* sink, - gpointer user_data) { +static GstFlowReturn OnGstAppsinkBuffer(GstAppSink* sink, gpointer user_data) { MediaSourcePlayerGstreamer* player = static_cast(user_data); if (!player || player->IsPlayerDestructing()) @@ -277,8 +164,8 @@ static GstFlowReturn on_gst_appsink_sample( return GST_FLOW_OK; } -gboolean on_gst_seek_audio_feed_cb( - GstAppSrc *pipeline, +gboolean OnGstSeekAudioFeedCB( + GstAppSrc* pipeline, guint64 offset, void* user_data) { MediaSourcePlayerGstreamer* player = @@ -289,8 +176,8 @@ gboolean on_gst_seek_audio_feed_cb( return TRUE; } -static void on_gst_start_audio_feed_cb ( - GstAppSrc * pipeline, +static void OnGstStartAudioFeedCB( + GstAppSrc* pipeline, guint size, void* user_data) { MediaSourcePlayerGstreamer* player = @@ -300,7 +187,7 @@ static void on_gst_start_audio_feed_cb ( player->OnReadDemuxedData(media::DemuxerStream::AUDIO); } -static void on_gst_stop_audio_feed_cb(GstAppSrc* pipeline, void* user_data) { +static void OnGstStopAudioFeedCB(GstAppSrc* pipeline, void* user_data) { MediaSourcePlayerGstreamer* player = static_cast(user_data); if (!player || player->IsPlayerDestructing()) @@ -309,7 +196,7 @@ static void on_gst_stop_audio_feed_cb(GstAppSrc* pipeline, void* user_data) { } #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) -static void on_video_sink_caps_changed_cb( +static void OnVideoSinkCapsChangedCB( GObject* gobject, GParamSpec* gparamspec, void* user_data) { @@ -321,14 +208,6 @@ static void on_video_sink_caps_changed_cb( } #endif -// Generating Unique string from given width and height. -std::string ConvertWidthAndHeightToString(int width, int height) { - std::ostringstream width_stream, height_stream; - width_stream << width; - height_stream << height; - return width_stream.str() + "X" + height_stream.str(); -} - MediaSourcePlayerGstreamer::MediaSourcePlayerGstreamer( int player_id, scoped_ptr demuxer, @@ -336,51 +215,37 @@ MediaSourcePlayerGstreamer::MediaSourcePlayerGstreamer( : MediaPlayerEfl(player_id, manager), demuxer_(demuxer.Pass()), main_loop_(base::MessageLoopProxy::current()), -#if defined(OS_TIZEN_TV) && !defined(TIZEN_V_3_0) - audio_session_manager_(AudioSessionManager::CreateAudioSessionManager()), -#endif playing_(false), weak_this_(this), #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) pixmap_id_(0), efl_pixmap_(NULL), - m_damage(0), - m_damageHandler(0), + m_damage_(0), + m_damage_handler_(0), #endif is_xwindow_handle_set_(false), - is_backed_by_pixmap(false), pipeline_(NULL), video_appsrc_(NULL), - video_parse_(NULL), - video_decoder_(NULL), + video_queue_(NULL), video_sink_(NULL), audio_appsrc_(NULL), - audio_decoder_(NULL), - audio_sink_(NULL), - video_queue_(NULL), audio_queue_(NULL), - audio_parse_(NULL), - audio_convert_(NULL), - audio_resampler_(NULL), audio_volume_(NULL), - video_sink_pad_(NULL), should_feed_audio_(true), should_feed_video_(false), - gst_width_(0), - gst_height_(0), + width_(0), + height_(0), video_format_(0), - media_type(0), + media_type_(0), play_rate_(1.0f), duration_(0), is_paused_due_underflow_(false), - shared_memory_size(0), buffered_(0), is_paused_(false), is_seeking_(false), is_demuxer_seeking_(false), audio_buffered_(0), video_buffered_(0), - is_gst_pipeline_constructed_(false), is_download_finished_(false), is_end_reached_(false), error_occured_(false), @@ -394,25 +259,12 @@ MediaSourcePlayerGstreamer::MediaSourcePlayerGstreamer( #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) efl_pixmaps_map_.clear(); #endif -#if defined(OS_TIZEN_TV) && !defined(TIZEN_V_3_0) - if (!audio_session_manager_->RegisterAudioSessionManager( - MM_SESSION_TYPE_SHARE, - media_player_private_audio_session_notify_cb, this)) - return; -#endif -} - -MediaSourcePlayerGstreamer::~MediaSourcePlayerGstreamer() { - VLOG(1) << "MediaSourcePlayerGstreamer::" << __FUNCTION__ - << "Player ID:" << GetPlayerId(); } void MediaSourcePlayerGstreamer::Destroy() { if (IsPlayerDestructing()) return; - VLOG(1) << "MediaSourcePlayerGstreamer::" << __FUNCTION__ - << "Player ID:" << GetPlayerId(); destructing_ = true; Release(); main_loop_->DeleteSoon(FROM_HERE, this); @@ -425,19 +277,8 @@ void MediaSourcePlayerGstreamer::Play() { playing_ = true; return; } -#if defined(OS_TIZEN_TV) && !defined(TIZEN_V_3_0) - if (!audio_session_manager_->SetSoundState(ASM_STATE_PLAYING)) - return; -#endif - VLOG(1) << "MediaSourcePlayerGstreamer::" << __FUNCTION__ - << "Player ID:" << GetPlayerId(); - -#if defined(OS_TIZEN_MOBILE) && (defined(TIZEN_V_2_3) || defined(TIZEN_V_2_4)) - if (device_power_wakeup(false) != DEVICE_ERROR_NONE) - LOG(ERROR) << "|device_power_wakeup| request failed"; - - if (device_power_request_lock(POWER_LOCK_DISPLAY, 0) != DEVICE_ERROR_NONE) - LOG(ERROR) << "|device_power_request_lock| request failed"; +#if defined(OS_TIZEN_MOBILE) + WakeUpDisplayAndAcquireDisplayLock(); #endif gst_element_set_state(pipeline_, GST_STATE_PLAYING); @@ -450,34 +291,20 @@ void MediaSourcePlayerGstreamer::Pause(bool is_media_related_action) { if (!pipeline_ || error_occured_) return; -#if defined(OS_TIZEN_TV) && !defined(TIZEN_V_3_0) - if (!audio_session_manager_->SetSoundState(ASM_STATE_PAUSE)) - return; -#endif - - VLOG(1) << "MediaSourcePlayerGstreamer::" << __FUNCTION__; gst_element_set_state(pipeline_, GST_STATE_PAUSED); - StopCurrentTimeUpdateTimer(); if (!is_media_related_action) { - -#if defined(OS_TIZEN_MOBILE) && (defined(TIZEN_V_2_3) || defined(TIZEN_V_2_4)) - if (device_power_release_lock(POWER_LOCK_DISPLAY) != DEVICE_ERROR_NONE) - LOG(ERROR) << "|device_power_release_lock| request failed"; +#if defined(OS_TIZEN_MOBILE) + ReleaseDisplayLock(); #endif - is_paused_due_underflow_ = false; playing_ = false; } } void MediaSourcePlayerGstreamer::SetRate(double rate) { - VLOG(1) << "MediaSourcePlayerGstreamer::" - << __FUNCTION__ << " : " << rate; - if (play_rate_ == rate) return; - if (rate == 0.0) { play_rate_ = rate; Pause(true); @@ -485,7 +312,7 @@ void MediaSourcePlayerGstreamer::SetRate(double rate) { } // If rate was zero and requested rate is non-zero, change the paused state - if(play_rate_ == 0.0 && rate != 0.0) { + if (play_rate_ == 0.0 && rate != 0.0) { Play(); StartCurrentTimeUpdateTimer(); } @@ -493,19 +320,12 @@ void MediaSourcePlayerGstreamer::SetRate(double rate) { play_rate_ = rate; RequestPlayerSeek(GetCurrentTime()); - -#if defined(OS_TIZEN_TV) && !defined(TIZEN_V_3_0) - if (!audio_session_manager_->SetSoundState(ASM_STATE_PAUSE)) - return; -#endif } void MediaSourcePlayerGstreamer::RequestPlayerSeek(double seekTime) { - VLOG(1) << "MediaSourcePlayerGstreamer::" << __FUNCTION__ - << " : " << seekTime; if (is_demuxer_seeking_) return; - GstState state; + GstState state = GST_STATE_VOID_PENDING; gst_element_get_state(pipeline_, &state, NULL, 250 * GST_NSECOND); is_demuxer_seeking_ = true; if (state == GST_STATE_PLAYING) @@ -514,13 +334,10 @@ void MediaSourcePlayerGstreamer::RequestPlayerSeek(double seekTime) { } void MediaSourcePlayerGstreamer::Seek(const double time) { - GstState state; + GstState state = GST_STATE_VOID_PENDING; gst_element_get_state(pipeline_, &state, NULL, 250 * GST_NSECOND); is_seeking_iframe_ = false; - VLOG(1) << "MediaSourcePlayerGstreamer::" << __FUNCTION__ - << " : " << time << " state : " << gst_element_state_get_name(state); - is_demuxer_seeking_ = true; if (state == GST_STATE_PLAYING) Pause(true); @@ -536,27 +353,23 @@ void MediaSourcePlayerGstreamer::SeekInternal(const GstClockTime position) { if (!pipeline_ || error_occured_) return; - GstClockTime startTime, endTime; + GstClockTime startTime = 0, endTime = position; is_demuxer_seeking_ = false; if (play_rate_ > 0) { startTime = position; endTime = GST_CLOCK_TIME_NONE; - } else { - startTime = 0; - endTime = position; } - VLOG(1) << "MediaSourcePlayerGstreamer::" << __FUNCTION__ - << " : " << position; - UpdateSeekState(true); audio_buffer_queue_.clear(); video_buffer_queue_.clear(); - if(!gst_element_seek(pipeline_, play_rate_, GST_FORMAT_TIME, - static_cast(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE), - GST_SEEK_TYPE_SET, startTime, GST_SEEK_TYPE_SET, endTime)) { + if (!gst_element_seek(pipeline_, play_rate_, GST_FORMAT_TIME, + static_cast(GST_SEEK_FLAG_FLUSH | + GST_SEEK_FLAG_ACCURATE), + GST_SEEK_TYPE_SET, startTime, GST_SEEK_TYPE_SET, + endTime)) { LOG(ERROR) << "Seek to " << position << " failed"; HandleError(MediaPlayerEfl::NetworkStateDecodeError); } @@ -568,16 +381,11 @@ double MediaSourcePlayerGstreamer::GetCurrentTime() { gint64 current_time = 0; GstFormat format = GST_FORMAT_TIME; -#if GST_VERSION_MAJOR == 1 gst_element_query_position(pipeline_, format, ¤t_time); -#else - gst_element_query_position(pipeline_, &format, ¤t_time); -#endif return ConvertNanoSecondsToSeconds(current_time); } void MediaSourcePlayerGstreamer::Release() { - VLOG(1) << "MediaSourcePlayerGstreamer::" << __FUNCTION__; DCHECK(IsPlayerDestructing()); playing_ = false; StopCurrentTimeUpdateTimer(); @@ -588,12 +396,10 @@ void MediaSourcePlayerGstreamer::Release() { GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline_)); if (bus) { g_signal_handlers_disconnect_by_func( - bus, reinterpret_cast(gst_pipeline_message_cb), this); -#if GST_VERSION_MAJOR == 1 + bus, + reinterpret_cast(GstPipelineMessageCB), + this); gst_bus_set_sync_handler(bus, NULL, NULL, NULL); -#else - gst_bus_set_sync_handler(bus, NULL, NULL); -#endif gst_object_unref(bus); } @@ -602,37 +408,21 @@ void MediaSourcePlayerGstreamer::Release() { pipeline_ = NULL; } - if (video_sink_pad_) - gst_object_unref(video_sink_pad_); - -#if defined(OS_TIZEN_TV) && !defined(TIZEN_V_3_0) - if (!audio_session_manager_->SetSoundState(ASM_STATE_STOP)) - return; - if (!audio_session_manager_->DeallocateResources()) - return; -#endif #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) UnregisterDamageHandler(); - EflPixmapMap::iterator it = efl_pixmaps_map_.begin(); - while (it != efl_pixmaps_map_.end()) { - efl_pixmap_ = it->second; - if (efl_pixmap_.get()) - efl_pixmap_ = NULL; - it++; - } efl_pixmaps_map_.clear(); #endif } #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) void MediaSourcePlayerGstreamer::UnregisterDamageHandler() { - if (m_damage) { - ecore_x_damage_free(m_damage); - m_damage = 0; + if (m_damage_) { + ecore_x_damage_free(m_damage_); + m_damage_ = 0; } - if (m_damageHandler) { - ecore_event_handler_del(m_damageHandler); - m_damageHandler = 0; + if (m_damage_handler_) { + ecore_event_handler_del(m_damage_handler_); + m_damage_handler_ = 0; } } #endif @@ -647,6 +437,17 @@ void MediaSourcePlayerGstreamer::OnDemuxerConfigsAvailable( if (IsPlayerDestructing()) return; + // Video elements + GstElement* video_parse = NULL; + GstElement* video_decoder = NULL; + + // Audio elements + GstElement* audio_decoder = NULL; + GstElement* audio_parse = NULL; + GstElement* audio_convert = NULL; + GstElement* audio_resampler = NULL; + GstElement* audio_sink = NULL; + if ((configs.video_codec == kUnknownVideoCodec || configs.video_codec != kCodecH264) && (configs.audio_codec == kUnknownAudioCodec || @@ -657,245 +458,258 @@ void MediaSourcePlayerGstreamer::OnDemuxerConfigsAvailable( return; } - gst_width_ = configs.video_size.width(); - gst_height_ = configs.video_size.height(); + width_ = configs.video_size.width(); + height_ = configs.video_size.height(); - if (is_gst_pipeline_constructed_) { + if (pipeline_ != NULL) return; - } - is_gst_pipeline_constructed_ = true; - GError* err = NULL; + if (!gst_is_initialized()) + gst_init_check(NULL, NULL, 0); + if (!gst_is_initialized()) { - gst_init_check(NULL, NULL, &err); + LOG(ERROR) << "Unable to initialize GST"; + HandleError(MediaPlayerEfl::NetworkStateDecodeError); + return; } - if (gst_is_initialized() && !err) { - pipeline_ = gst_pipeline_new(kPipelineName); - if (!pipeline_) { - LOG(ERROR) << "Unable to Create |Pipeline|"; - HandleError(MediaPlayerEfl::NetworkStateDecodeError); - return; - } - - int i = 0; - while (VideoMapping[i].codec != kUnknownVideoCodec) { - if (configs.video_codec == VideoMapping[i].codec) { - media_type |= MEDIA_VIDEO_MASK; - video_appsrc_ = gst_element_factory_make("appsrc", "video-source"); - video_parse_ = gst_element_factory_make(VideoMapping[i].elements[0], - "video-parse"); - video_queue_ = gst_element_factory_make("queue2", "video-queue"); - video_decoder_ = gst_element_factory_make(VideoMapping[i].elements[1], - "video-decoder"); - -#if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) - PrepareForVideoSink(); -#else - PrepareForVideoFrame(); -#endif + pipeline_ = gst_pipeline_new(kPipelineName); + if (!pipeline_) { + LOG(ERROR) << "Unable to Create |Pipeline|"; + HandleError(MediaPlayerEfl::NetworkStateDecodeError); + return; + } + for (int i = 0; VideoMapping[i].codec != kUnknownVideoCodec; i++) { + if (configs.video_codec == VideoMapping[i].codec) { + media_type_ |= MEDIA_VIDEO_MASK; + video_appsrc_ = gst_element_factory_make("appsrc", "video-source"); + if (video_appsrc_ && !gst_bin_add(GST_BIN(pipeline_), video_appsrc_)) { + gst_object_unref(video_appsrc_); + HandleError(MediaPlayerEfl::NetworkStateDecodeError); + return; + } + video_parse = gst_element_factory_make(VideoMapping[i].elements[0], + "video-parse"); + if (video_parse && !gst_bin_add(GST_BIN(pipeline_), video_parse)) { + gst_object_unref(video_parse); + HandleError(MediaPlayerEfl::NetworkStateDecodeError); + return; + } + video_queue_ = gst_element_factory_make("queue2", "video-queue"); + if (video_queue_ && !gst_bin_add(GST_BIN(pipeline_), video_queue_)) { + gst_object_unref(video_queue_); + HandleError(MediaPlayerEfl::NetworkStateDecodeError); + return; + } + video_decoder = gst_element_factory_make(VideoMapping[i].elements[1], + "video-decoder"); + if (video_decoder && !gst_bin_add(GST_BIN(pipeline_), video_decoder)) { + gst_object_unref(video_decoder); + HandleError(MediaPlayerEfl::NetworkStateDecodeError); + return; + } #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) - if (is_backed_by_pixmap) - CreatePixmap(); -#endif - if (!video_appsrc_ || !video_parse_ || !video_queue_ || - !video_decoder_ || !video_sink_) { - LOG(ERROR) << "Not all elements of video pipeline could be created"; - ReleaseVideoElements(); - HandleError(MediaPlayerEfl::NetworkStateDecodeError); - return; - } - - g_object_set(GST_OBJECT(video_appsrc_), "format", GST_FORMAT_TIME, NULL); - g_object_set(GST_OBJECT(video_appsrc_), "stream-type", - GST_APP_STREAM_TYPE_SEEKABLE, NULL); - g_object_set(GST_OBJECT(video_appsrc_), "do-timestamp", false, NULL); - - // Will make the queue to send GST_MESSAGE_BUFFERING - g_object_set(G_OBJECT(video_queue_), "use-buffering", true, NULL); - - // Will trigger need-data callback if buffer goes below 30%, - // default is 10%. Data type of property "low-percent" differs - // on desktop and TIZEN platform. -#if GST_VERSION_MAJOR < 1 - g_object_set(G_OBJECT(video_queue_), "low-percent", (double)30.0, NULL); + PrepareForVideoSink(); + CreatePixmap(); #else - g_object_set(G_OBJECT(video_queue_), "low-percent", 30, NULL); + PrepareForVideoFrame(); #endif + if (video_sink_ && !gst_bin_add(GST_BIN(pipeline_), video_sink_)) { + gst_object_unref(video_sink_); + HandleError(MediaPlayerEfl::NetworkStateDecodeError); + return; + } - gst_bin_add_many(GST_BIN(pipeline_), video_appsrc_, video_queue_, - video_parse_, video_decoder_, video_sink_, NULL); - - // Why |video_queue_| is placed after |video_appsrc_|? - // For understanding puprose consider http://tinyurl.com/qos-iron url. - // For 1080p resolution of the video in above url, each decoded frame - // is of size 2304000 bytes ~ 2.19 MB. If video_queue_ is placed before - // |video_sink_| then queue will buffer decoded frames, so to buffer - // two second worth of data queue will require 2304000*24(fps)*2 ~ 96MB - // of queue size. This property can't be set for pixmap backed playback - // as frame size won't be available for pixmap backed | video_sink|. - // And this size varies from video to video. - // - // But if |video_queue_| is placed after |video_appsrc_|, queue will - // buffer encoded data. For the same video of 1080p, maximum encoded - // frame is of 115398byte ~ 0.110052109 MB. So for 2 sec data, queue - // need to buffer 5308308bytes in queue ~ 5MB, this can be set - // dynamically. Refer |OnDemuxerDataAvailable| for setting queue size. - - gst_element_link_many(video_appsrc_,video_queue_, video_parse_, - video_decoder_, video_sink_, NULL); - static GstAppSrcCallbacks video_callbacks = { - on_gst_start_video_feed_cb, - on_gst_stop_video_feed_cb, - on_gst_seek_video_feed_cb, {NULL}}; - - // FIXME: Try fourth argument for destructy notification. - gst_app_src_set_callbacks(GST_APP_SRC(video_appsrc_), &video_callbacks, - this, NULL); - break; + g_object_set(GST_OBJECT(video_appsrc_), "format", GST_FORMAT_TIME, + NULL); + g_object_set(GST_OBJECT(video_appsrc_), "stream-type", + GST_APP_STREAM_TYPE_SEEKABLE, NULL); + g_object_set(GST_OBJECT(video_appsrc_), "do-timestamp", false, NULL); + + // Will make the queue to send GST_MESSAGE_BUFFERING + g_object_set(G_OBJECT(video_queue_), "use-buffering", true, NULL); + + // Why |video_queue_| is placed after |video_appsrc_|? + // For understanding puprose consider http://tinyurl.com/qos-iron url. + // For 1080p resolution of the video in above url, each decoded frame + // is of size 2304000 bytes ~ 2.19 MB. If video_queue_ is placed before + // |video_sink_| then queue will buffer decoded frames, so to buffer + // two second worth of data queue will require 2304000*24(fps)*2 ~ 96MB + // of queue size. This property can't be set for pixmap backed playback + // as frame size won't be available for pixmap backed |video_sink|. And + // this size varies from video to video. + // + // But if |video_queue_| is placed after |video_appsrc_|, queue will + // buffer encoded data. For the same video of 1080p, maximum encoded + // frame is of 115398byte ~ 0.110052109 MB. So for 2 sec data, queue + // need to buffer 5308308bytes in queue ~ 5MB, this can be set + // dynamically. Refer |OnDemuxerDataAvailable| for setting queue size. + + if (!gst_element_link_many(video_appsrc_, video_queue_, video_parse, + video_decoder, video_sink_, NULL)) { + LOG(ERROR) << "Video pipeline couldn't be created / linked"; + HandleError(MediaPlayerEfl::NetworkStateDecodeError); + return; } - i++; - } - i = 0; - while (AudioMapping[i].codec != kUnknownAudioCodec) { - if(configs.audio_codec == AudioMapping[i].codec) { - media_type |= MEDIA_AUDIO_MASK; - audio_appsrc_ = gst_element_factory_make("appsrc", "audio-source"); - audio_queue_ = gst_element_factory_make("queue2", "audio-queue"); - audio_parse_ = gst_element_factory_make(AudioMapping[i].elements[0], - "audio-parse"); - audio_decoder_ = gst_element_factory_make(AudioMapping[i].elements[1], - "audio-decoder"); - audio_convert_ = gst_element_factory_make("audioconvert", "audio-convert"); - audio_resampler_ = gst_element_factory_make( - "audioresample", "audio-resample"); - audio_volume_ = gst_element_factory_make("volume", "volume"); - audio_sink_ = gst_element_factory_make( - AudioMapping[i].elements[2], "audio-sink"); - - if (!audio_appsrc_ || !audio_queue_ || !audio_parse_ || - !audio_decoder_ || !audio_convert_ || !audio_resampler_ || - !audio_volume_ || !audio_sink_) { - LOG(ERROR) << "Not all elements of audio pipeline could be created"; - ReleaseAudioElements(); - HandleError(MediaPlayerEfl::NetworkStateDecodeError); - return; - } + GstAppSrcCallbacks video_callbacks = { + OnGstStartVideoFeedCB, + OnGstStopVideoFeedCB, + OnGstSeekVideoFeedCB, + {NULL}}; - g_object_set( - GST_OBJECT(audio_appsrc_),"format", GST_FORMAT_TIME, NULL); - g_object_set(GST_OBJECT(audio_appsrc_),"stream-type", - GST_APP_STREAM_TYPE_SEEKABLE, NULL); - g_object_set(GST_OBJECT(audio_appsrc_), "do-timestamp", false, NULL); + gst_app_src_set_callbacks(GST_APP_SRC(video_appsrc_), &video_callbacks, + this, NULL); + break; + } + } - g_object_set(G_OBJECT(audio_queue_), "use-buffering", true, NULL); + for (int i = 0; AudioMapping[i].codec != kUnknownAudioCodec; i++) { + if (configs.audio_codec == AudioMapping[i].codec) { + media_type_ |= MEDIA_AUDIO_MASK; + audio_appsrc_ = gst_element_factory_make("appsrc", "audio-source"); + if (audio_appsrc_ && !gst_bin_add(GST_BIN(pipeline_), audio_appsrc_)) { + gst_object_unref(audio_appsrc_); + HandleError(MediaPlayerEfl::NetworkStateDecodeError); + return; + } -#if GST_VERSION_MAJOR < 1 - g_object_set( - G_OBJECT(audio_queue_), "low-percent", (double)30.0, NULL); -#else - g_object_set(G_OBJECT(audio_queue_), "low-percent", 30, NULL); -#endif + audio_queue_ = gst_element_factory_make("queue2", "audio-queue"); + if (audio_queue_ && !gst_bin_add(GST_BIN(pipeline_), audio_queue_)) { + gst_object_unref(audio_queue_); + HandleError(MediaPlayerEfl::NetworkStateDecodeError); + return; + } - g_object_set(G_OBJECT(audio_volume_), "mute", false, NULL); + audio_parse = gst_element_factory_make(AudioMapping[i].elements[0], + "audio-parse"); + if (audio_parse && !gst_bin_add(GST_BIN(pipeline_), audio_parse)) { + gst_object_unref(audio_parse); + HandleError(MediaPlayerEfl::NetworkStateDecodeError); + return; + } -#if defined(OS_TIZEN_TV) && !defined(TIZEN_V_3_0) - if (!audio_session_manager_->AllocateResources(audio_decoder_)) - return; + audio_decoder = gst_element_factory_make(AudioMapping[i].elements[1], + "audio-decoder"); + if (audio_decoder && !gst_bin_add(GST_BIN(pipeline_), audio_decoder)) { + gst_object_unref(audio_decoder); + HandleError(MediaPlayerEfl::NetworkStateDecodeError); + return; + } - g_object_set(audio_sink_, "provide-clock", true, "device", "hw:0,0", NULL); - if (!audio_session_manager_->AllocateResources(audio_sink_)) - return; -#endif + audio_convert = gst_element_factory_make("audioconvert", + "audio-convert"); + if (audio_convert && !gst_bin_add(GST_BIN(pipeline_), audio_convert)) { + gst_object_unref(audio_convert); + HandleError(MediaPlayerEfl::NetworkStateDecodeError); + return; + } - gst_bin_add_many(GST_BIN(pipeline_), audio_appsrc_, audio_queue_, - audio_parse_, audio_decoder_, audio_convert_, audio_resampler_, - audio_volume_, audio_sink_, NULL); + audio_resampler = gst_element_factory_make("audioresample", + "audio-resample"); + if (audio_resampler && + !gst_bin_add(GST_BIN(pipeline_), audio_resampler)) { + gst_object_unref(audio_resampler); + HandleError(MediaPlayerEfl::NetworkStateDecodeError); + return; + } - gst_element_link_many(audio_appsrc_, audio_queue_, audio_parse_, - audio_decoder_, audio_convert_, audio_resampler_, audio_volume_, - audio_sink_, NULL); + audio_volume_ = gst_element_factory_make("volume", "volume"); + if (audio_volume_ && !gst_bin_add(GST_BIN(pipeline_), audio_volume_)) { + gst_object_unref(audio_volume_); + HandleError(MediaPlayerEfl::NetworkStateDecodeError); + return; + } - static GstAppSrcCallbacks audio_callbacks = { - on_gst_start_audio_feed_cb, - on_gst_stop_audio_feed_cb, - on_gst_seek_audio_feed_cb, {NULL}}; + audio_sink = gst_element_factory_make(AudioMapping[i].elements[2], + "audio-sink"); + if (audio_sink && !gst_bin_add(GST_BIN(pipeline_), audio_sink)) { + gst_object_unref(audio_sink); + HandleError(MediaPlayerEfl::NetworkStateDecodeError); + return; + } - gst_app_src_set_callbacks(GST_APP_SRC(audio_appsrc_), &audio_callbacks, - this, NULL); - break; + g_object_set(GST_OBJECT(audio_appsrc_), "format", GST_FORMAT_TIME, + NULL); + g_object_set(GST_OBJECT(audio_appsrc_), "stream-type", + GST_APP_STREAM_TYPE_SEEKABLE, NULL); + g_object_set(GST_OBJECT(audio_appsrc_), "do-timestamp", false, NULL); + g_object_set(G_OBJECT(audio_queue_), "use-buffering", true, NULL); + g_object_set(G_OBJECT(audio_volume_), "mute", false, NULL); + + if (!gst_element_link_many(audio_appsrc_, audio_queue_, audio_parse, + audio_decoder, audio_convert, + audio_resampler, audio_volume_, + audio_sink, NULL)) { + LOG(ERROR) << "Not all elements of audio pipeline could be linked"; + HandleError(MediaPlayerEfl::NetworkStateDecodeError); } - i++; - } - GstBus*bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline_)); - if (!bus) { - LOG(ERROR) << "GStreamer bus creation failed"; - HandleError(MediaPlayerEfl::NetworkStateDecodeError); - return; + GstAppSrcCallbacks audio_callbacks = { + OnGstStartAudioFeedCB, + OnGstStopAudioFeedCB, + OnGstSeekAudioFeedCB, + {NULL}}; + gst_app_src_set_callbacks(GST_APP_SRC(audio_appsrc_), + &audio_callbacks, this, NULL); + break; } -#if GST_VERSION_MAJOR == 1 - gst_bus_set_sync_handler( - bus, (GstBusSyncHandler)gst_pipeline_message_cb, this, NULL); -#else - gst_bus_set_sync_handler( - bus, (GstBusSyncHandler)gst_pipeline_message_cb, this); -#endif - gst_object_unref(bus); + } - manager()->OnMediaDataChange(GetPlayerId(), video_format_, - gst_height_, gst_width_, media_type); + GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline_)); + if (!bus) { + LOG(ERROR) << "GStreamer bus creation failed"; + HandleError(MediaPlayerEfl::NetworkStateDecodeError); + return; + } + gst_bus_set_sync_handler( + bus, + static_cast(GstPipelineMessageCB), + this, + NULL); + gst_object_unref(bus); - manager()->OnReadyStateChange(GetPlayerId(), - MediaPlayerEfl::ReadyStateHaveMetadata); + manager()->OnMediaDataChange(GetPlayerId(), video_format_, height_, + width_, media_type_); + manager()->OnReadyStateChange(GetPlayerId(), + MediaPlayerEfl::ReadyStateHaveMetadata); - if (gst_element_set_state(pipeline_, GST_STATE_PAUSED) == - GST_STATE_CHANGE_FAILURE) - LOG(ERROR) << "GStreamer state change failed"; - } else { - LOG(ERROR) << "Unable to initialize GST"; - HandleError(MediaPlayerEfl::NetworkStateDecodeError); + if (gst_element_set_state(pipeline_, GST_STATE_PAUSED) == + GST_STATE_CHANGE_FAILURE) { + LOG(ERROR) << "GStreamer state change failed"; } } #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) void MediaSourcePlayerGstreamer::PrepareForVideoSink() { video_sink_ = gst_element_factory_make("xvimagesink", "sink"); - if ( video_sink_ == NULL) { - PrepareForVideoFrame(); - } else { - VLOG(1) << "MediaSource using |xvimagesink| for Video Playback"; - is_backed_by_pixmap = true; - video_sink_pad_ = gst_element_get_static_pad(video_sink_, "sink"); - if (video_sink_pad_) { - g_signal_connect(video_sink_pad_, "notify::caps", - G_CALLBACK(on_video_sink_caps_changed_cb), this); - } else { - LOG(ERROR) << " |video_sink_pad_| is NULL ?"; + DCHECK(video_sink_ != NULL) << "Failed to initialize xvimagesink."; + if (video_sink_ != NULL) { + GstPad* video_sink_pad = gst_element_get_static_pad(video_sink_, "sink"); + if (!video_sink_pad) { + LOG(ERROR) << "GStreamer sink could not be obtained"; + HandleError(MediaPlayerEfl::NetworkStateDecodeError); + return; } + g_signal_connect(video_sink_pad, "notify::caps", + static_cast(OnVideoSinkCapsChangedCB), this); + gst_object_unref(video_sink_pad); } } #endif void MediaSourcePlayerGstreamer::PrepareForVideoFrame() { is_xwindow_handle_set_ = true; - VLOG(1) << "MediaSource using |appsink| for Video Playback"; video_sink_ = gst_element_factory_make("appsink", "sink"); -#if GST_VERSION_MAJOR == 1 - GstAppSinkCallbacks callbacks = {NULL, on_gst_appsink_preroll, - on_gst_appsink_sample}; -#else - GstAppSinkCallbacks callbacks = {NULL, - on_gst_appsink_preroll, - on_gst_appsink_sample, - NULL, - {NULL, NULL, NULL}}; -#endif - gst_app_sink_set_callbacks(GST_APP_SINK(video_sink_), &callbacks, this, - NULL); - g_object_set(G_OBJECT(video_sink_), "max-buffers", (guint)1, NULL); + GstAppSinkCallbacks callbacks = { + NULL, + OnGstAppsinkPreroll, + OnGstAppsinkBuffer}; + gst_app_sink_set_callbacks(GST_APP_SINK(video_sink_), + &callbacks, this, NULL); + g_object_set(G_OBJECT(video_sink_), "max-buffers", + static_cast(1), NULL); } void MediaSourcePlayerGstreamer::ReadDemuxedData( @@ -908,8 +722,7 @@ void MediaSourcePlayerGstreamer::ReadDemuxedData( } else if (type == media::DemuxerStream::VIDEO) { should_feed_video_ = true; } else { - LOG(ERROR) << "Unknown Media Type in MediaSourcePlayerGstreamer::" - << __FUNCTION__; + LOG(ERROR) << "Unknown Media Type"; return; } demuxer_->RequestDemuxerData(type); @@ -918,12 +731,13 @@ void MediaSourcePlayerGstreamer::ReadDemuxedData( void MediaSourcePlayerGstreamer::OnReadDemuxedData( media::DemuxerStream::Type type) { if (IsPlayerDestructing()) { - LOG(ERROR) << __FUNCTION__ << "GST is deinitializing. Just return"; + LOG(ERROR) << "GST is deinitializing. Just return"; return; } - main_loop_->PostTask(FROM_HERE, base::Bind( - &MediaSourcePlayerGstreamer::ReadDemuxedData, base::Unretained(this), - type)); + main_loop_->PostTask( + FROM_HERE, base::Bind(&MediaSourcePlayerGstreamer::ReadDemuxedData, + base::Unretained(this), + type)); } void MediaSourcePlayerGstreamer::OnStopDemuxedData( @@ -933,8 +747,7 @@ void MediaSourcePlayerGstreamer::OnStopDemuxedData( else if (type == media::DemuxerStream::VIDEO) should_feed_video_ = false; else - LOG(ERROR) << "Unknown Media Type in MediaSourcePlayerGstreamer::" - << __FUNCTION__; + LOG(ERROR) << "Unknown media stream!"; } void MediaSourcePlayerGstreamer::OnDemuxerDataAvailable( @@ -944,31 +757,34 @@ void MediaSourcePlayerGstreamer::OnDemuxerDataAvailable( LOG(ERROR) << "Pipeline_ null or error occured"; return; } + if (meta_data.status != media::DemuxerStream::kOk || + meta_data.end_of_stream) + BufferMetaDataAvailable(meta_data); if (meta_data.size <= 0) { LOG(ERROR) << "ERROR : Size of shared memory is Zero"; return; } + int64 metadata_timestamp_in_ms = meta_data.timestamp.InMicroseconds() * 1000; if (is_seeking_ && !is_seeking_iframe_) { if (meta_data.type == media::DemuxerStream::VIDEO) { is_seeking_iframe_ = true; if (video_seek_offset_ > - (guint64)(meta_data.timestamp.InMicroseconds() * 1000)) { - RequestPlayerSeek((double)(ConvertNanoSecondsToSeconds( - meta_data.timestamp.InMicroseconds() * 1000 - + kSixteenMilliSeconds))); + static_cast(metadata_timestamp_in_ms)) { + int64 time = metadata_timestamp_in_ms + kSixteenMilliSeconds; + RequestPlayerSeek(ConvertNanoSecondsToSeconds(time)); return; } } else if (meta_data.type == media::DemuxerStream::AUDIO) { - if ( audio_seek_offset_ > - (guint64)(meta_data.timestamp.InMicroseconds() * 1000)) + if (audio_seek_offset_ > + static_cast(metadata_timestamp_in_ms)) return; } } ReadFromQueueIfAny(meta_data.type); if (meta_data.type == media::DemuxerStream::VIDEO) { - if (meta_data.size > raw_video_frame_size_) { + if (meta_data.size != raw_video_frame_size_) { // Dynamically Changing Video Queue Size for Smooth Playback. // The default queue size limits are 100 buffers, 2MB of data, // or two seconds worth of data, whichever is reached first. @@ -986,11 +802,11 @@ void MediaSourcePlayerGstreamer::OnDemuxerDataAvailable( raw_video_frame_size_ * no_frames_per_two_second; if (no_frames_per_two_second > 100) { g_object_set(G_OBJECT(video_queue_), "max-size-buffers", - no_frames_per_two_second, NULL); + static_cast(no_frames_per_two_second), NULL); } - if (queue_size_for_two_sec > 2097152) { + if (queue_size_for_two_sec > 2 * kBytesPerMegabyte) { g_object_set(G_OBJECT(video_queue_), "max-size-bytes", - queue_size_for_two_sec, NULL); + static_cast(queue_size_for_two_sec), NULL); } } } @@ -1006,38 +822,37 @@ void MediaSourcePlayerGstreamer::OnDemuxerDataAvailable( return; } + // Wrapping each frame and deleting shared memory using callback + // will not work as possibility of Gstreamer retaining frames (such as + // 'i' frames) is high. In that case shared memory will crash. So, we + // copy frames and release shared memory right away. + base::SharedMemory shared_memory(foreign_memory_handle, false); - shared_memory.Map(meta_data.size); - void* ptr; + if (!shared_memory.Map(meta_data.size)) { + LOG(ERROR) << "Failed to map shared memory of size " << meta_data.size; + return; + } gint size = meta_data.size; GstFlowReturn ret = GST_FLOW_OK; - ptr = g_malloc(size); - memcpy(ptr, shared_memory.memory(), size); + GstBuffer* buffer = gst_buffer_new_allocate(NULL, size, NULL); + gst_buffer_fill(buffer, 0, shared_memory.memory(), size); -#if GST_VERSION_MAJOR == 1 - GstBuffer* buffer = gst_buffer_new_allocate(NULL, meta_data.size, NULL); - gst_buffer_fill (buffer, 0, ptr, meta_data.size); -#else - GstBuffer* buffer = gst_buffer_new(); - GST_BUFFER_MALLOCDATA(buffer) = (uint8*)ptr; - GST_BUFFER_SIZE(buffer) = size; - GST_BUFFER_DATA(buffer) = GST_BUFFER_MALLOCDATA(buffer); -#endif - GST_BUFFER_TIMESTAMP (buffer) = - (guint64)(meta_data.timestamp.InMicroseconds() * 1000); - GST_BUFFER_DURATION (buffer) = - (guint64)(meta_data.time_duration.InMicroseconds() * 1000); + GST_BUFFER_TIMESTAMP(buffer) = + static_cast(metadata_timestamp_in_ms); + GST_BUFFER_DURATION(buffer) = + static_cast(meta_data.time_duration.InMicroseconds() * 1000); if (meta_data.type == media::DemuxerStream::AUDIO) - ret = gst_app_src_push_buffer(GST_APP_SRC(audio_appsrc_), buffer); + ret = gst_app_src_push_buffer(GST_APP_SRC(audio_appsrc_), + buffer); else if (meta_data.type == media::DemuxerStream::VIDEO) - ret = gst_app_src_push_buffer(GST_APP_SRC(video_appsrc_), buffer); + ret = gst_app_src_push_buffer(GST_APP_SRC(video_appsrc_), + buffer); // gst_app_src_push_buffer() takes ownership of the buffer. // Hence no need to unref buffer. if (ret != GST_FLOW_OK) { - LOG(ERROR) << __FUNCTION__ << " : Gstreamer appsrc push failed : " << ret; - shared_memory.Close(); + LOG(ERROR) << "Gstreamer appsrc push failed : " << ret; return; } @@ -1045,13 +860,11 @@ void MediaSourcePlayerGstreamer::OnDemuxerDataAvailable( OnReadDemuxedData(media::DemuxerStream::AUDIO); else if (meta_data.type == media::DemuxerStream::VIDEO && should_feed_video_) OnReadDemuxedData(media::DemuxerStream::VIDEO); - shared_memory.Close(); return; } -void MediaSourcePlayerGstreamer::OnBufferMetaDataAvailable( +void MediaSourcePlayerGstreamer::BufferMetaDataAvailable( const media::DemuxedBufferMetaData& meta_data) { - if (!pipeline_ || error_occured_) { LOG(ERROR) << "Pipeline_ null or error occured"; return; @@ -1059,11 +872,10 @@ void MediaSourcePlayerGstreamer::OnBufferMetaDataAvailable( switch (meta_data.status) { case media::DemuxerStream::kAborted: - // FIXME : Need to handle Aborted state Properly. if (meta_data.type == media::DemuxerStream::AUDIO && should_feed_audio_) OnReadDemuxedData(media::DemuxerStream::AUDIO); else if (meta_data.type == media::DemuxerStream::VIDEO && - should_feed_video_) + should_feed_video_) OnReadDemuxedData(media::DemuxerStream::VIDEO); break; @@ -1071,13 +883,8 @@ void MediaSourcePlayerGstreamer::OnBufferMetaDataAvailable( if (meta_data.type == media::DemuxerStream::AUDIO && should_feed_audio_) OnReadDemuxedData(media::DemuxerStream::AUDIO); else if (meta_data.type == media::DemuxerStream::VIDEO && - should_feed_video_) + should_feed_video_) OnReadDemuxedData(media::DemuxerStream::VIDEO); - - if (meta_data.type == media::DemuxerStream::AUDIO) - VLOG(1) << "[BROWSER] : AUDIO::kConfigChanged"; - if (meta_data.type == media::DemuxerStream::VIDEO) - VLOG(1) << "[BROWSER] : VIDEO::kConfigChanged"; break; case media::DemuxerStream::kOk: @@ -1124,24 +931,25 @@ void MediaSourcePlayerGstreamer::ReadFromQueueIfAny( video_buffer_queue_.pop_front(); } - void* ptr; + // Wrapping each frame and deleting shared memory using callback + // will not work as possibility of Gstreamer retaining frames (such as + // 'i' frames) is high. In that case shared memory will crash. So, we + // copy frames and release shared memory right away. + GstFlowReturn ret; gint size = decoder_buffer.get()->data_size(); - ptr = g_malloc(size); - memcpy(ptr, (void*)decoder_buffer.get()->writable_data(), size); -#if GST_VERSION_MAJOR == 1 GstBuffer* buffer = gst_buffer_new_allocate(NULL, size, NULL); - gst_buffer_fill (buffer, 0, ptr, size); -#else - GstBuffer* buffer = gst_buffer_new(); - GST_BUFFER_MALLOCDATA(buffer) = (uint8*)ptr; - GST_BUFFER_SIZE(buffer) = size; - GST_BUFFER_DATA(buffer) = GST_BUFFER_MALLOCDATA(buffer); -#endif - GST_BUFFER_TIMESTAMP (buffer) = - (guint64)(decoder_buffer.get()->timestamp().InMicroseconds() * 1000); - GST_BUFFER_DURATION (buffer) = - (guint64)(decoder_buffer.get()->duration().InMicroseconds() * 1000); + if (!buffer) + return; + + gst_buffer_fill(buffer, 0, decoder_buffer.get()->writable_data(), size); + + GST_BUFFER_TIMESTAMP(buffer) = + static_cast(decoder_buffer.get()->timestamp().InMicroseconds() * + 1000); + GST_BUFFER_DURATION(buffer) = + static_cast(decoder_buffer.get()->duration().InMicroseconds() * + 1000); if (type == media::DemuxerStream::AUDIO) ret = gst_app_src_push_buffer(GST_APP_SRC(audio_appsrc_), buffer); @@ -1150,7 +958,7 @@ void MediaSourcePlayerGstreamer::ReadFromQueueIfAny( if (ret != GST_FLOW_OK) return; - //Empty the Buffer before reading the new buffer from render process. + // Empty the Buffer before reading the new buffer from render process. ReadFromQueueIfAny(type); return; } @@ -1164,14 +972,16 @@ void MediaSourcePlayerGstreamer::SaveDecoderBuffer( } base::SharedMemory shared_memory(foreign_memory_handle, false); - shared_memory.Map(meta_data.size); + if (!shared_memory.Map(meta_data.size)) { + LOG(ERROR) << "Failed to map shared memory of size " << meta_data.size; + return; + } scoped_refptr buffer; buffer = DecoderBuffer::CopyFrom(static_cast ( shared_memory.memory()), meta_data.size); if (!buffer.get()) { LOG(ERROR) << "DecoderBuffer::CopyFrom failed"; - shared_memory.Close(); return; } @@ -1182,150 +992,99 @@ void MediaSourcePlayerGstreamer::SaveDecoderBuffer( audio_buffer_queue_.push_back(buffer); else video_buffer_queue_.push_back(buffer); - - shared_memory.Close(); } void MediaSourcePlayerGstreamer::GetFrameDetails() { if (!pipeline_ || error_occured_) return; - GstState state; - GstState pending; - GstStateChangeReturn ret = gst_element_get_state(pipeline_, - &state, &pending, 250 * GST_NSECOND); - VLOG(1) << "MediaSourcePlayerGstreamer::" - << __FUNCTION__ - << " GstStateChangeReturn: " - << gst_element_state_change_return_get_name(ret) - << " state: " - << gst_element_state_get_name(state) - << " pending: " - << gst_element_state_get_name(pending) - << " ID " << GetPlayerId(); + GstState state = GST_STATE_VOID_PENDING; + GstState pending = GST_STATE_VOID_PENDING; + gst_element_get_state(pipeline_, &state, &pending, 250 * GST_NSECOND); // Get details only after prerolling. if (pending >= GST_STATE_PAUSED) - main_loop_->PostTask(FROM_HERE, base::Bind( - &MediaSourcePlayerGstreamer::OnGetFrameDetails, - base::Unretained(this))); + main_loop_->PostTask( + FROM_HERE, + base::Bind(&MediaSourcePlayerGstreamer::OnGetFrameDetails, + base::Unretained(this))); } void MediaSourcePlayerGstreamer::OnGetFrameDetails() { if (!pipeline_ || IsPlayerDestructing() || error_occured_) return; -#if GST_VERSION_MAJOR == 1 + GstSample* sample = gst_app_sink_pull_preroll(GST_APP_SINK(video_sink_)); if (!sample) return; - GstCaps* caps = gst_sample_get_caps(sample); - if (!caps) - return; - - GstVideoInfo vi; - gst_video_info_from_caps(&vi, caps); - - gst_width_ = GST_VIDEO_INFO_WIDTH(&vi); - gst_height_ = GST_VIDEO_INFO_HEIGHT(&vi); - switch(GST_VIDEO_INFO_FORMAT(&vi)) { - case GST_VIDEO_FORMAT_I420:{ - video_format_ = GST_MAKE_FOURCC('I','4','2','0'); - break; - } - case GST_VIDEO_FORMAT_NV12:{ - video_format_ = GST_MAKE_FOURCC('N','V','1','2'); - break; - } - default: - LOG(ERROR) << "Unknown format : " << GST_VIDEO_INFO_FORMAT(&vi); - break; - } -#else - - GstBuffer* sample = gst_app_sink_pull_preroll(GST_APP_SINK(video_sink_)); - - if (!sample) - return; - GstCaps* caps = gst_buffer_get_caps(GST_BUFFER(sample)); - if (!caps) { - gst_buffer_unref(sample); + if (!GetGstVideoBufferMetaData(sample, &width_, + &height_, &video_format_)) { + gst_sample_unref(sample); return; } - // No need to unref |GstStructure| - const GstStructure* str = gst_caps_get_structure(caps, 0); - gst_caps_unref(caps); - gst_buffer_unref(sample); - if (!str) - return; + gst_sample_unref(sample); - if (!gst_structure_get_int(str, "width", &gst_width_) || - !gst_structure_get_int(str, "height", &gst_height_) || - !gst_structure_get_fourcc(str, "format", &video_format_)) { - LOG(ERROR) << "Pre-rolled sample information could not be obtained"; - } -#endif + if (video_format_ == GST_VIDEO_SN12) + sn12_bufsize_ = GetSN12BufferSize(width_, height_); - if(video_format_ == GST_VIDEO_SN12) { - uint tile_w_align = ((gst_width_ - 1) / SN12_TILE_WIDTH + 2) & ~1; - bufsize_sn12_ = - SN12_TILE_SIZE * tile_w_align * ((gst_height_-1)/SN12_TILE_HEIGHT+1) - + (((gst_height_+1)&~1)/2) * tile_w_align * SN12_TILE_WIDTH; - } - manager()->OnMediaDataChange(GetPlayerId(), video_format_, - gst_height_, gst_width_, media_type); + manager()->OnMediaDataChange(GetPlayerId(), video_format_, height_, + width_, media_type_); } -#if GST_VERSION_MAJOR == 1 GstSample* MediaSourcePlayerGstreamer::PullSample() { return gst_app_sink_pull_sample(GST_APP_SINK(video_sink_)); } void MediaSourcePlayerGstreamer::OnNewFrameAvailable(GstSample* sample) { - if (!pipeline_ || error_occured_) + if (!sample) + return; + + if (!pipeline_ || error_occured_) { + gst_sample_unref(sample); return; + } GstMapInfo map; GstBuffer* buffer = gst_sample_get_buffer(sample); if (!gst_buffer_map(buffer, &map, GST_MAP_READ)) { - LOG (ERROR) << "Sample contains invalid or no info!"; + LOG(ERROR) << "Sample contains invalid or no info!"; return; } - if (!gst_width_ || !gst_height_) + if (!width_ || !height_) GetFrameDetails(); + int width; + int height; + if (!GetGstVideoBufferMetaData(sample, &width, + &height, NULL)) { + gst_sample_unref(sample); + return; + } - GstCaps* caps = gst_sample_get_caps(sample); - if (caps) { - GstVideoInfo vi; - gst_video_info_from_caps(&vi, caps); - int width = GST_VIDEO_INFO_WIDTH(&vi); - int height = GST_VIDEO_INFO_HEIGHT(&vi); - - if (width != gst_width_|| height != gst_height_) { - LOG (INFO) << __FUNCTION__ - << " ###### from " << gst_width_ << "X" << gst_height_ - << " to " << width << "X" << height; - gst_width_ = width; - gst_height_ = height; - manager()->OnMediaDataChange( - GetPlayerId(), video_format_, gst_height_, gst_width_, media_type); - } + if (width != width_ || height != height_) { + width_ = width; + height_ = height; + manager()->OnMediaDataChange(GetPlayerId(), video_format_, height_, + width_, media_type_); } + base::SharedMemory shared_memory; + uint32 shared_memory_size = 0; + base::SharedMemoryHandle foreign_memory_handle; base::TimeDelta timestamp = base::TimeDelta::FromMicroseconds( GST_BUFFER_TIMESTAMP(buffer) / base::Time::kNanosecondsPerMicrosecond); - if(video_format_ == GST_VIDEO_SN12) - shared_memory_size = (bufsize_sn12_); + if (video_format_ == GST_VIDEO_SN12) + shared_memory_size = (sn12_bufsize_); else shared_memory_size = (map.size); if (!shared_memory.CreateAndMapAnonymous(shared_memory_size)) { - LOG (ERROR) << "Shared Memory creation failed."; + LOG(ERROR) << "Shared Memory creation failed."; gst_buffer_unmap(buffer, &map); gst_sample_unref(sample); return; @@ -1333,8 +1092,7 @@ void MediaSourcePlayerGstreamer::OnNewFrameAvailable(GstSample* sample) { if (!shared_memory.ShareToProcess(base::Process::Current().Handle(), &foreign_memory_handle)) { - LOG (ERROR) << "Shared Memory handle could not be obtained"; - shared_memory.Close(); + LOG(ERROR) << "Shared Memory handle could not be obtained"; gst_buffer_unmap(buffer, &map); gst_sample_unref(sample); return; @@ -1344,96 +1102,25 @@ void MediaSourcePlayerGstreamer::OnNewFrameAvailable(GstSample* sample) { manager()->OnNewFrameAvailable( GetPlayerId(), foreign_memory_handle, shared_memory_size, timestamp); - shared_memory.Close(); gst_buffer_unmap(buffer, &map); gst_sample_unref(sample); } -#else -GstBuffer* MediaSourcePlayerGstreamer::PullSample() { - return gst_app_sink_pull_buffer(GST_APP_SINK(video_sink_)); -} - -void MediaSourcePlayerGstreamer::OnNewFrameAvailable(const GstBuffer* buffer) { - if (!pipeline_ || error_occured_) - return; - if (!buffer) - return; - if (!GST_BUFFER_DATA(buffer) || !GST_BUFFER_SIZE(buffer)) - return; - - if (!gst_width_ || !gst_height_) - GetFrameDetails(); - // FIXME: Cross check the end results. - base::TimeDelta timestamp = - base::TimeDelta::FromMicroseconds( - GST_BUFFER_TIMESTAMP(buffer) / - base::Time::kNanosecondsPerMicrosecond); - - uint8* buffer_data = GST_BUFFER_DATA(buffer); - gsize buffer_size = GST_BUFFER_SIZE(buffer); - - if(video_format_ == GST_VIDEO_SN12) - shared_memory_size = (bufsize_sn12_); - else - shared_memory_size = (buffer_size); - - if (!shared_memory.CreateAndMapAnonymous(shared_memory_size)) { - LOG (ERROR) << "Shared Memory creation failed."; - gst_buffer_unref(GST_BUFFER(buffer)); - return; - } - - if (!shared_memory.ShareToProcess(base::Process::Current().Handle(), - &foreign_memory_handle)) { - LOG (ERROR) << "Shared Memory handle could not be obtained"; - shared_memory.Close(); - gst_buffer_unref(GST_BUFFER(buffer)); - return; - } - - memcpy(shared_memory.memory(), buffer_data, shared_memory_size); - manager()->OnNewFrameAvailable( - GetPlayerId(), foreign_memory_handle, shared_memory_size, timestamp); - - shared_memory.Close(); - gst_buffer_unref(GST_BUFFER(buffer)); -} -#endif #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) void MediaSourcePlayerGstreamer::XWindowIdPrepared(GstMessage* message) { - gint width, height; -#if GST_VERSION_MAJOR == 1 const GstStructure* structure = gst_message_get_structure(message); - gst_structure_get_int(structure, "video-width", &width); - gst_structure_get_int(structure, "video-height", &height); -#else - gst_structure_get_int(message->structure, "video-width", &width); - gst_structure_get_int(message->structure, "video-height", &height); -#endif - if ((gst_width_ != width) || (gst_height_ != height)) { - LOG(ERROR) << "Demuxer Video Configs and Gstreamer Video Configs doesn't" - <<" match.From Demuxer : width : "<OnMediaDataChange( - GetPlayerId(), video_format_, gst_height_, gst_width_, media_type); + manager()->OnMediaDataChange(GetPlayerId(), video_format_, height_, + width_, media_type_); } void MediaSourcePlayerGstreamer::PlatformSurfaceUpdated() { gint64 current_time = 0; GstFormat format = GST_FORMAT_TIME; -#if GST_VERSION_MAJOR == 1 gst_element_query_position(pipeline_, format, ¤t_time); -#else - gst_element_query_position(pipeline_, &format, ¤t_time); -#endif base::TimeDelta timestamp = base::TimeDelta::FromMicroseconds( current_time / base::Time::kNanosecondsPerMicrosecond); manager()->OnPlatformSurfaceUpdated(GetPlayerId(), pixmap_id_, timestamp); @@ -1444,9 +1131,6 @@ int MediaSourcePlayerGstreamer::GetSurfaceID() const { } void MediaSourcePlayerGstreamer::SetPixmap() { -#if GST_VERSION_MAJOR == 1 - gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(video_sink_), pixmap_id_); -#else #if defined(OS_TIZEN_TV) // Using below statements on mobile to set pixmap was causing two issue. // 1. Video size was different than the required one whenever configaration @@ -1454,16 +1138,15 @@ void MediaSourcePlayerGstreamer::SetPixmap() { // 2. Sometime black screen was appearing, while video was playing. // Hence for mobile keeping implementation which uses // |gst_x_overlay_set_window_handle|to sep Pixmap. - g_object_set (video_sink_, "pixmap-id-callback", get_pixmap_id_cb, NULL); - g_object_set (video_sink_, "pixmap-id-callback-userdata", this, NULL); + g_object_set(video_sink_, "pixmap-id-callback", GetPixmapIdCB, NULL); + g_object_set(video_sink_, "pixmap-id-callback-userdata", this, NULL); #else gst_x_overlay_set_window_handle(GST_X_OVERLAY(video_sink_), pixmap_id_); #endif -#endif - m_damage = ecore_x_damage_new(pixmap_id_, - ECORE_X_DAMAGE_REPORT_RAW_RECTANGLES); - m_damageHandler = ecore_event_handler_add(ECORE_X_EVENT_DAMAGE_NOTIFY, - notify_damage_updated_cb, this); + m_damage_ = ecore_x_damage_new(pixmap_id_, + ECORE_X_DAMAGE_REPORT_RAW_RECTANGLES); + m_damage_handler_ = ecore_event_handler_add(ECORE_X_EVENT_DAMAGE_NOTIFY, + NotifyDamageUpdatedCB, this); g_object_set(video_sink_, "rotate", 0, NULL); is_xwindow_handle_set_ = true; } @@ -1471,59 +1154,57 @@ void MediaSourcePlayerGstreamer::SetPixmap() { void MediaSourcePlayerGstreamer::OnVideoConfigsChanged() { if (!pipeline_ || error_occured_) return; - main_loop_->PostTask(FROM_HERE, base::Bind( - &MediaSourcePlayerGstreamer::VideoConfigsChanged, - base::Unretained(this))); + main_loop_->PostTask( + FROM_HERE, + base::Bind(&MediaSourcePlayerGstreamer::VideoConfigsChanged, + base::Unretained(this))); } void MediaSourcePlayerGstreamer::VideoConfigsChanged() { if (!pipeline_ || IsPlayerDestructing() || error_occured_) return; - VLOG(1) << "Video Configs Changed, so changing the pixmap"; - gint width, height; - -#if GST_VERSION_MAJOR == 1 - GstCaps* caps = gst_pad_get_current_caps(GST_PAD(video_sink_pad_)); - if (caps) { - GstVideoInfo info; - gst_video_info_init(&info); - - if (gst_video_info_from_caps(&info, caps)) { - width = info.width; - height = info.height; - } + + GstPad* video_sink_pad = gst_element_get_static_pad(video_sink_, "sink"); + GstCaps* caps = gst_pad_get_current_caps(GST_PAD(video_sink_pad)); + if (!caps) { + LOG(ERROR) << "Cannot get CAPS!"; + gst_object_unref(video_sink_pad); + return; } -#else - if (gst_video_get_size(video_sink_pad_, &width, &height)) { - LOG(ERROR) << "Cannot get width / height!"; + + GstVideoInfo info; + gst_video_info_init(&info); + if (!gst_video_info_from_caps(&info, caps)) { + LOG(ERROR) << "Cannot get information from CAPS!"; + gst_caps_unref(caps); + gst_object_unref(video_sink_pad); return; } -#endif - if ((gst_width_ != width) || (gst_height_ != height)) { + + if ((width_ != info.width) || (height_ != info.height)) { LOG(ERROR) << "Demuxer Video Configs and Gstreamer Video Configs doesn't" - <<" match.From Demuxer : width : "<OnMediaDataChange( - GetPlayerId(), video_format_, gst_height_, gst_width_, media_type); + GetPlayerId(), video_format_, height_, width_, media_type_); } + gst_caps_unref(caps); + gst_object_unref(video_sink_pad); } void MediaSourcePlayerGstreamer::CreatePixmap() { - bool is_create_new = false; - std::string string_wh = - ConvertWidthAndHeightToString(gst_width_, gst_height_); - if (efl_pixmaps_map_.size() == 0) - is_create_new = true; + bool is_create_new = efl_pixmaps_map_.empty(); + int int_wh = GetUniqueKey(width_, height_); if (!is_create_new) { - EflPixmapMap::iterator it = efl_pixmaps_map_.find(string_wh); + EflPixmapMap::iterator it = efl_pixmaps_map_.find(int_wh); if (it != efl_pixmaps_map_.end()) { is_create_new = false; efl_pixmap_ = it->second; @@ -1535,13 +1216,13 @@ void MediaSourcePlayerGstreamer::CreatePixmap() { if (is_create_new) { efl_pixmap_ = gfx::EflPixmap::Create(gfx::EflPixmap::SURFACE, - gfx::Size(gst_width_, gst_height_)); + gfx::Size(width_, height_)); if (!efl_pixmap_.get()) { LOG(ERROR) << "gfx::EflPixmap::Create() failed to create Pixmap"; return; } pixmap_id_ = efl_pixmap_->GetId(); - efl_pixmaps_map_[string_wh] = efl_pixmap_; + efl_pixmaps_map_[int_wh] = efl_pixmap_; } } #endif @@ -1553,17 +1234,15 @@ void MediaSourcePlayerGstreamer::OnDemuxerDurationChanged( void MediaSourcePlayerGstreamer::OnDemuxerSeekDone( const base::TimeDelta& actual_browser_seek_time) { - VLOG(1) << "MediaSourcePlayerGstreamer::" << __FUNCTION__ << " : " - << actual_browser_seek_time.InSecondsF(); SeekInternal(ConvertToGstClockTime(actual_browser_seek_time.InSecondsF())); } bool MediaSourcePlayerGstreamer::HasVideo() { - return media_type & MEDIA_VIDEO_MASK; + return media_type_ & MEDIA_VIDEO_MASK; } bool MediaSourcePlayerGstreamer::HasAudio() { - return media_type & MEDIA_AUDIO_MASK; + return media_type_ & MEDIA_AUDIO_MASK; } void MediaSourcePlayerGstreamer::OnCurrentTimeUpdateTimerFired() { @@ -1575,7 +1254,8 @@ void MediaSourcePlayerGstreamer::StartCurrentTimeUpdateTimer() { current_time_update_timer_.Start( FROM_HERE, base::TimeDelta::FromMilliseconds(kDurationUpdateInterval), - this, &MediaSourcePlayerGstreamer::OnCurrentTimeUpdateTimerFired); + this, + &MediaSourcePlayerGstreamer::OnCurrentTimeUpdateTimerFired); } } @@ -1587,121 +1267,95 @@ void MediaSourcePlayerGstreamer::StopCurrentTimeUpdateTimer() { void MediaSourcePlayerGstreamer::HandleMessage(GstMessage* message) { if (!pipeline_ || error_occured_) return; - if (!strcmp(kPipelineName, GST_MESSAGE_SRC_NAME(message))) - VLOG(1) << "MediaSourcePlayerGstreamer::" << __FUNCTION__ - << " Message " << GST_MESSAGE_TYPE_NAME(message) - << " received from element " << GST_MESSAGE_SRC_NAME(message) - << " ID " << GetPlayerId(); switch (GST_MESSAGE_TYPE(message)) { - case GST_MESSAGE_ELEMENT: -#if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) - if (!IsXWindowHadleSet() && -#if GST_VERSION_MAJOR == 1 - gst_is_video_overlay_prepare_window_handle_message(message)) { -#else - message->structure && - gst_structure_has_name(message->structure, "prepare-xid")) { -#endif - LOG(INFO) << "Received message : Video overlay prepared"; - XWindowIdPrepared(message); - return; - } -#endif - case GST_MESSAGE_ERROR: - GError* error; - gst_message_parse_error(message, &error, NULL); - MediaPlayerEfl::NetworkState network_state_error; - network_state_error = MediaPlayerEfl::NetworkStateEmpty; - if (error->code == GST_STREAM_ERROR_CODEC_NOT_FOUND - || error->code == GST_STREAM_ERROR_WRONG_TYPE - || error->code == GST_STREAM_ERROR_FAILED - || error->code == GST_RESOURCE_ERROR_NOT_FOUND) { - network_state_error = MediaPlayerEfl::NetworkStateFormatError; - } else if (error->domain == GST_RESOURCE_ERROR) { - network_state_error = MediaPlayerEfl::NetworkStateNetworkError; - } else { - network_state_error = MediaPlayerEfl::NetworkStateDecodeError; - } -#if defined(OS_TIZEN_TV) && !defined(TIZEN_V_3_0) - if (!audio_session_manager_->SetSoundState(ASM_STATE_STOP)) - return; - if (!audio_session_manager_->DeallocateResources()) - return; -#endif - LOG(ERROR) << "Error Message : " << error->message << " Recieved From : " - << GST_MESSAGE_SRC_NAME(message) - << ", and Blink Error Code = " << network_state_error; - g_error_free(error); - HandleError(network_state_error); - break; - case GST_MESSAGE_EOS: - VLOG(1) << "GST_MESSAGE_EOS"; -#if defined(OS_TIZEN_TV) && !defined(TIZEN_V_3_0) - if (!audio_session_manager_->SetSoundState(ASM_STATE_STOP)) - return; - if (!audio_session_manager_->DeallocateResources()) - return; -#endif - main_loop_->PostTask(FROM_HERE, base::Bind( - &MediaSourcePlayerGstreamer::OnPlaybackComplete, - base::Unretained(this))); - break; - case GST_MESSAGE_ASYNC_DONE: - VLOG(1) << "HandleMessage : GST_MESSAGE_ASYNC_DONE : is_seeking_ = " - << is_seeking_; - if (is_seeking_) { - is_seeking_iframe_ = false; - main_loop_->PostTask(FROM_HERE, base::Bind( - &MediaSourcePlayerGstreamer::UpdateSeekState, - base::Unretained(this), false)); - - // Initiate play for internal seeks. - if (playing_) - main_loop_->PostTask(FROM_HERE, base::Bind( - &MediaSourcePlayerGstreamer::Play, base::Unretained(this))); + case GST_MESSAGE_ERROR: { + GError* error = NULL; + MediaPlayerEfl::NetworkState network_state_error = + MediaPlayerEfl::NetworkStateEmpty; + gst_message_parse_error(message, &error, NULL); + if (error->code == GST_STREAM_ERROR_CODEC_NOT_FOUND || + error->code == GST_STREAM_ERROR_WRONG_TYPE || + error->code == GST_STREAM_ERROR_FAILED || + error->code == GST_RESOURCE_ERROR_NOT_FOUND) { + network_state_error = MediaPlayerEfl::NetworkStateFormatError; + } else if (error->domain == GST_RESOURCE_ERROR) { + network_state_error = MediaPlayerEfl::NetworkStateNetworkError; + } else { + network_state_error = MediaPlayerEfl::NetworkStateDecodeError; + } - manager()->OnTimeUpdate(GetPlayerId(), GetCurrentTime()); - main_loop_->PostTask(FROM_HERE, base::Bind( - &MediaSourcePlayerGstreamer::OnTimeChanged, base::Unretained(this))); + LOG(ERROR) << "Error Message : " << error->message << " Recieved From : " + << GST_MESSAGE_SRC_NAME(message) + << ", and Blink Error Code = " << network_state_error; + g_error_free(error); + HandleError(network_state_error); + break; } - - // FIXME: Do we need to pull caps from PARSER? Can ignore if its of no use. - break; - case GST_MESSAGE_STATE_CHANGED: - if (strcmp(kPipelineName, GST_MESSAGE_SRC_NAME(message))) + case GST_MESSAGE_EOS: + main_loop_->PostTask(FROM_HERE, base::Bind( + &MediaSourcePlayerGstreamer::OnPlaybackComplete, + base::Unretained(this))); break; - main_loop_->PostTask(FROM_HERE, base::Bind( - &MediaSourcePlayerGstreamer::OnUpdateStates, base::Unretained(this))); - break; - case GST_MESSAGE_BUFFERING: - int buffered; - gst_message_parse_buffering(message, &buffered); - - if (audio_queue_ && GST_MESSAGE_SRC(message) == GST_OBJECT(audio_queue_)) - audio_buffered_ = buffered; - if (video_queue_ && GST_MESSAGE_SRC(message) == GST_OBJECT(video_queue_)) - video_buffered_ = buffered; - - if (!is_paused_due_underflow_ && playing_) { - if (audio_buffered_ < 100 || video_buffered_ < 100) { - main_loop_->PostTask(FROM_HERE, base::Bind( - &MediaSourcePlayerGstreamer::HandleBufferingMessage, - base::Unretained(this))); + case GST_MESSAGE_ASYNC_DONE: + if (is_seeking_) { + is_seeking_iframe_ = false; + main_loop_->PostTask( + FROM_HERE, + base::Bind(&MediaSourcePlayerGstreamer::UpdateSeekState, + base::Unretained(this), + false)); + + // Initiate play for internal seeks. + if (playing_) + main_loop_->PostTask(FROM_HERE, + base::Bind(&MediaSourcePlayerGstreamer::Play, + base::Unretained(this))); + + manager()->OnTimeUpdate(GetPlayerId(), GetCurrentTime()); + main_loop_->PostTask( + FROM_HERE, + base::Bind(&MediaSourcePlayerGstreamer::OnTimeChanged, + base::Unretained(this))); } - } else if (is_paused_due_underflow_ && playing_) { - if ((!HasAudio() || audio_buffered_ == 100) && - (!HasVideo() || video_buffered_ == 100)) { - main_loop_->PostTask(FROM_HERE, base::Bind( - &MediaSourcePlayerGstreamer::HandleBufferingMessage, - base::Unretained(this))); + break; + case GST_MESSAGE_STATE_CHANGED: + if (strcmp(kPipelineName, GST_MESSAGE_SRC_NAME(message))) + break; + main_loop_->PostTask( + FROM_HERE, + base::Bind(&MediaSourcePlayerGstreamer::OnUpdateStates, + base::Unretained(this))); + break; + case GST_MESSAGE_BUFFERING: { + int buffered = 0; + gst_message_parse_buffering(message, &buffered); + + if (audio_queue_ && GST_MESSAGE_SRC(message) == + GST_OBJECT(audio_queue_)) + audio_buffered_ = buffered; + else if (video_queue_ && GST_MESSAGE_SRC(message) == + GST_OBJECT(video_queue_)) + video_buffered_ = buffered; + + if (playing_) { + main_loop_->PostTask( + FROM_HERE, + base::Bind(&MediaSourcePlayerGstreamer::HandleBufferingMessage, + base::Unretained(this))); } + break; } - break; - default: - VLOG(1) << "Unhandled GStreamer message type: " - << GST_MESSAGE_TYPE_NAME(message); - break; + case GST_MESSAGE_ELEMENT: +#if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) + if (!IsXWindowHadleSet() && + gst_is_video_overlay_prepare_window_handle_message(message)) { + XWindowIdPrepared(message); + } + break; +#endif + default: + break; } } @@ -1710,32 +1364,20 @@ void MediaSourcePlayerGstreamer::OnUpdateStates() { if (!pipeline_ || IsPlayerDestructing() || error_occured_) return; - GstState state; - GstState pending; + GstState state = GST_STATE_VOID_PENDING; + GstState pending = GST_STATE_VOID_PENDING; GstStateChangeReturn ret = gst_element_get_state( pipeline_, &state, &pending, 250 * GST_NSECOND); - VLOG(1) << "MediaSourcePlayerGstreamer::" - << __FUNCTION__ - << " GstStateChangeReturn: " - << gst_element_state_change_return_get_name(ret) - << " state: " - << gst_element_state_get_name(state) - << " pending: " - << gst_element_state_get_name(pending) - << " ID " << GetPlayerId(); - - // FIXME: Handle all state changes switch (ret) { case GST_STATE_CHANGE_SUCCESS: switch (state) { case GST_STATE_PAUSED: manager()->OnReadyStateChange( - GetPlayerId(), MediaPlayerEfl::ReadyStateHaveEnoughData); + GetPlayerId(), + MediaPlayerEfl::ReadyStateHaveEnoughData); break; default: - VLOG(1) << "GStreamer unhandled state " - << gst_element_state_get_name(state); break; } break; @@ -1747,10 +1389,7 @@ void MediaSourcePlayerGstreamer::OnUpdateStates() { HandleError(MediaPlayerEfl::NetworkStateDecodeError); break; case GST_STATE_CHANGE_NO_PREROLL: - - break; default: - VLOG(1) << "Unhandled return type: " << ret; break; } } @@ -1759,21 +1398,26 @@ void MediaSourcePlayerGstreamer::HandleBufferingMessage() { if (IsPlayerDestructing()) return; if (!is_paused_due_underflow_ && - (audio_buffered_ < 100 || video_buffered_ < 100)) { + ((HasAudio() && audio_buffered_ < kMaxBufPercent) || + (HasVideo() && video_buffered_ < kMaxBufPercent))) { is_paused_due_underflow_ = true; Pause(true); - manager()->OnReadyStateChange(GetPlayerId(), + manager()->OnReadyStateChange( + GetPlayerId(), MediaPlayerEfl::ReadyStateHaveCurrentData); - manager()->OnNetworkStateChange(GetPlayerId(), + manager()->OnNetworkStateChange( + GetPlayerId(), MediaPlayerEfl::NetworkStateLoading); } else if (is_paused_due_underflow_ && - (!HasAudio() || audio_buffered_ == 100) && - (!HasVideo() || video_buffered_ == 100)) { + (!HasAudio() || audio_buffered_ == kMaxBufPercent) && + (!HasVideo() || video_buffered_ == kMaxBufPercent)) { is_paused_due_underflow_ = false; Play(); - manager()->OnReadyStateChange(GetPlayerId(), + manager()->OnReadyStateChange( + GetPlayerId(), MediaPlayerEfl::ReadyStateHaveEnoughData); - manager()->OnNetworkStateChange(GetPlayerId(), + manager()->OnNetworkStateChange( + GetPlayerId(), MediaPlayerEfl::NetworkStateLoaded); } } @@ -1786,12 +1430,9 @@ void MediaSourcePlayerGstreamer::OnPlaybackComplete() { StopCurrentTimeUpdateTimer(); manager()->OnTimeUpdate(GetPlayerId(), time); manager()->OnTimeChanged(GetPlayerId()); - -#if defined(OS_TIZEN_MOBILE) && (defined(TIZEN_V_2_3) || defined(TIZEN_V_2_4)) - if (device_power_release_lock(POWER_LOCK_DISPLAY) != DEVICE_ERROR_NONE) - LOG(ERROR) << "|device_power_release_lock| request failed"; +#if defined(OS_TIZEN_MOBILE) + ReleaseDisplayLock(); #endif - } void MediaSourcePlayerGstreamer::UpdateSeekState(bool state) { @@ -1800,7 +1441,6 @@ void MediaSourcePlayerGstreamer::UpdateSeekState(bool state) { } void MediaSourcePlayerGstreamer::OnTimeChanged() { - VLOG(1) << "OnTimeChanged" << "Player ID : " << GetPlayerId(); DCHECK(main_loop_->BelongsToCurrentThread()); manager()->OnTimeChanged(GetPlayerId()); } @@ -1809,81 +1449,9 @@ void MediaSourcePlayerGstreamer::HandleError( media::MediaPlayerEfl::NetworkState state) { error_occured_ = true; manager()->OnNetworkStateChange(GetPlayerId(), state); - -#if defined(OS_TIZEN_MOBILE) && (defined(TIZEN_V_2_3) || defined(TIZEN_V_2_4)) - if (device_power_release_lock(POWER_LOCK_DISPLAY) != DEVICE_ERROR_NONE) - LOG(ERROR) << "|device_power_release_lock| request failed"; +#if defined(OS_TIZEN_MOBILE) + ReleaseDisplayLock(); #endif - -} - -void MediaSourcePlayerGstreamer::ReleaseAudioElements() { - if (audio_appsrc_) { - gst_object_unref(audio_appsrc_); - audio_appsrc_ = NULL; - } - - if (audio_queue_) { - gst_object_unref(audio_queue_); - audio_queue_ = NULL; - } - - if (audio_parse_) { - gst_object_unref(audio_parse_); - audio_parse_ = NULL; - } - - if (audio_decoder_) { - gst_object_unref(audio_decoder_); - audio_decoder_ = NULL; - } - - if (audio_convert_) { - gst_object_unref(audio_convert_); - audio_convert_ = NULL; - } - - if (audio_resampler_) { - gst_object_unref(audio_resampler_); - audio_resampler_ = NULL; - } - - if (audio_volume_) { - gst_object_unref(audio_volume_); - audio_volume_ = NULL; - } - - if (audio_sink_) { - gst_object_unref(audio_sink_); - audio_sink_ = NULL; - } -} - -void MediaSourcePlayerGstreamer::ReleaseVideoElements() { - if(video_appsrc_) { - gst_object_unref(video_appsrc_); - video_appsrc_ = NULL; - } - - if(video_parse_) { - gst_object_unref(video_parse_); - video_parse_ = NULL; - } - - if(video_queue_) { - gst_object_unref(video_queue_); - video_queue_ = NULL; - } - - if(video_decoder_) { - gst_object_unref(video_decoder_); - video_decoder_ = NULL; - } - - if(video_sink_) { - gst_object_unref(video_sink_); - video_sink_ = NULL; - } } } // namespace media diff --git a/tizen_src/chromium_impl/media/base/efl/media_source_player_gstreamer.h b/tizen_src/chromium_impl/media/base/efl/media_source_player_gstreamer.h index af502b7..3330846 100644 --- a/tizen_src/chromium_impl/media/base/efl/media_source_player_gstreamer.h +++ b/tizen_src/chromium_impl/media/base/efl/media_source_player_gstreamer.h @@ -2,13 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef MEDIA_BASE_TIZEN_MEDIA_SOURCE_PLAYER_GSTREAMER_H_ -#define MEDIA_BASE_TIZEN_MEDIA_SOURCE_PLAYER_GSTREAMER_H_ - -#include +#ifndef MEDIA_BASE_EFL_MEDIA_SOURCE_PLAYER_GSTREAMER_H_ +#define MEDIA_BASE_EFL_MEDIA_SOURCE_PLAYER_GSTREAMER_H_ #include -#include "ecore_x_wrapper.h" +#include #include #include "base/cancelable_callback.h" @@ -24,21 +22,17 @@ #include "ui/gl/efl_pixmap.h" #endif -#if defined(OS_TIZEN_TV) && !defined(TIZEN_V_3_0) -#include "media/audio/tizen/audio_session_manager.h" -#endif - namespace { struct AudioCodecGstElementsMapping { media::AudioCodec codec; - const char **elements; + const char** elements; }; struct VideoCodecGstElementsMapping { media::VideoCodec codec; - const char **elements; + const char** elements; }; -} +} // namespace namespace media { @@ -46,7 +40,6 @@ namespace media { class MEDIA_EXPORT MediaSourcePlayerGstreamer : public MediaPlayerEfl, public DemuxerEflClient { public: - // Constructs a player with the given ID and demuxer. |manager| must outlive // the lifetime of this object. MediaSourcePlayerGstreamer( @@ -54,41 +47,34 @@ class MEDIA_EXPORT MediaSourcePlayerGstreamer : public MediaPlayerEfl, scoped_ptr demuxer, MediaPlayerManager* manager); - virtual ~MediaSourcePlayerGstreamer(); + ~MediaSourcePlayerGstreamer() override {}; // MediaPlayerEfl implementation. - virtual void Play() override; - virtual void Pause(bool is_media_related_action) override; - virtual void SetRate(double rate) override; - virtual void Seek(const double time) override; - virtual void SetVolume(double volume) override; - virtual double GetCurrentTime() override; - virtual void Destroy() override; + void Play() override; + void Pause(bool is_media_related_action) override; + void SetRate(double rate) override; + void Seek(const double time) override; + void SetVolume(double volume) override; + double GetCurrentTime() override; + void Destroy() override; // DemuxerEflClient implementation. - virtual void OnDemuxerConfigsAvailable( + void OnDemuxerConfigsAvailable( const DemuxerConfigs& params) override; - virtual void OnDemuxerDataAvailable( + void OnDemuxerDataAvailable( base::SharedMemoryHandle foreign_memory_handle, const media::DemuxedBufferMetaData& meta_data) override; - virtual void OnBufferMetaDataAvailable( - const media::DemuxedBufferMetaData& meta_data) override; - virtual void OnDemuxerSeekDone( + void OnDemuxerSeekDone( const base::TimeDelta& actual_browser_seek_time) override; - virtual void OnDemuxerDurationChanged(base::TimeDelta duration) override; + void OnDemuxerDurationChanged(base::TimeDelta duration) override; // GStreamer Message handler void HandleMessage(GstMessage* message); // AppSink related void GetFrameDetails(); -#if GST_VERSION_MAJOR == 1 GstSample* PullSample(); void OnNewFrameAvailable(GstSample* sample); -#else - GstBuffer* PullSample(); - void OnNewFrameAvailable(const GstBuffer* buffer); -#endif #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) void PlatformSurfaceUpdated(); @@ -107,7 +93,7 @@ class MEDIA_EXPORT MediaSourcePlayerGstreamer : public MediaPlayerEfl, } protected: - virtual void Release() override; + void Release() override; private: void PrepareForVideoFrame(); @@ -117,10 +103,11 @@ class MEDIA_EXPORT MediaSourcePlayerGstreamer : public MediaPlayerEfl, void VideoConfigsChanged(); void CreatePixmap(); void SetPixmap(); - bool IsXWindowHadleSet() { return is_xwindow_handle_set_;} - void XWindowIdPrepared(GstMessage*); + bool IsXWindowHandleSet() { return is_xwindow_handle_set_;} + void XWindowIdPrepared(GstMessage* message); void UnregisterDamageHandler(); #endif + void BufferMetaDataAvailable(const media::DemuxedBufferMetaData& meta_data); void ReadDemuxedData(media::DemuxerStream::Type type); void SaveDecoderBuffer( @@ -131,14 +118,9 @@ class MEDIA_EXPORT MediaSourcePlayerGstreamer : public MediaPlayerEfl, bool HasAudio(); bool HasVideo(); - // Note: Must be invoked only if elements are not added into the pipeline. - void ReleaseAudioElements(); - void ReleaseVideoElements(); - - void SeekInternal(const GstClockTime time); - // For internal seeks. void RequestPlayerSeek(double seekTime); + void SeekInternal(const GstClockTime time); // |current_time_update_timer_| related void OnCurrentTimeUpdateTimerFired(); @@ -159,10 +141,6 @@ class MEDIA_EXPORT MediaSourcePlayerGstreamer : public MediaPlayerEfl, const scoped_refptr main_loop_; -#if defined(OS_TIZEN_TV) && !defined(TIZEN_V_3_0) - scoped_refptr audio_session_manager_; -#endif - // Stats about the media. bool playing_; @@ -173,50 +151,34 @@ class MEDIA_EXPORT MediaSourcePlayerGstreamer : public MediaPlayerEfl, #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) int pixmap_id_; scoped_refptr efl_pixmap_; - Ecore_X_Damage m_damage; - Ecore_Event_Handler* m_damageHandler; - typedef std::map > EflPixmapMap; + Ecore_X_Damage m_damage_; + Ecore_Event_Handler* m_damage_handler_; + typedef std::map > EflPixmapMap; EflPixmapMap efl_pixmaps_map_; #endif // Will allow to listen to |prepare-xid| message only once. bool is_xwindow_handle_set_; - // Whenever resolution changes, to change the pixmap - // if Video Playback is backed by |pixmap|. - bool is_backed_by_pixmap; - GstElement* pipeline_; GstElement* video_appsrc_; - GstElement* video_parse_; - GstElement* video_decoder_; + GstElement* video_queue_; GstElement* video_sink_; GstElement* audio_appsrc_; - GstElement* audio_decoder_; - GstElement* audio_sink_; - GstElement* video_queue_; GstElement* audio_queue_; - GstElement* audio_parse_; - GstElement* audio_convert_; - GstElement* audio_resampler_; GstElement* audio_volume_; - GstPad* video_sink_pad_; bool should_feed_audio_; bool should_feed_video_; - int gst_width_; - int gst_height_; + int width_; + int height_; guint32 video_format_; - int media_type; - int bufsize_sn12_; + int media_type_; + int sn12_bufsize_; double play_rate_; double duration_; bool is_paused_due_underflow_; - base::SharedMemory shared_memory; - uint32 shared_memory_size; - base::SharedMemoryHandle foreign_memory_handle; - int buffered_; bool is_paused_; bool is_seeking_; @@ -224,7 +186,6 @@ class MEDIA_EXPORT MediaSourcePlayerGstreamer : public MediaPlayerEfl, int audio_buffered_; int video_buffered_; - bool is_gst_pipeline_constructed_; std::deque > audio_buffer_queue_; std::deque > video_buffer_queue_; @@ -251,4 +212,4 @@ class MEDIA_EXPORT MediaSourcePlayerGstreamer : public MediaPlayerEfl, } // namespace media -#endif // MEDIA_BASE_TIZEN_MEDIA_SOURCE_PLAYER_GSTREAMER_H_ +#endif // MEDIA_BASE_EFL_MEDIA_SOURCE_PLAYER_GSTREAMER_H_ diff --git a/tizen_src/chromium_impl/media/base/efl/webaudio_media_codec_info_efl.h b/tizen_src/chromium_impl/media/base/efl/webaudio_media_codec_info_efl.h index b44c056..170ea4f 100644 --- a/tizen_src/chromium_impl/media/base/efl/webaudio_media_codec_info_efl.h +++ b/tizen_src/chromium_impl/media/base/efl/webaudio_media_codec_info_efl.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef MEDIA_BASE_TIZEN_WEBAUDIO_MEDIA_CODEC_INFO_EFL_H_ -#define MEDIA_BASE_TIZEN_WEBAUDIO_MEDIA_CODEC_INFO_EFL_H_ +#ifndef MEDIA_BASE_EFL_WEBAUDIO_MEDIA_CODEC_INFO_EFL_H_ +#define MEDIA_BASE_EFL_WEBAUDIO_MEDIA_CODEC_INFO_EFL_H_ namespace media { @@ -17,4 +17,4 @@ struct WebAudioMediaCodecInfoEfl { }; } // namespace media -#endif // MEDIA_BASE_TIZEN_WEBAUDIO_MEDIA_CODEC_INFO_EFL_H_ +#endif // MEDIA_BASE_EFL_WEBAUDIO_MEDIA_CODEC_INFO_EFL_H_ \ No newline at end of file diff --git a/tizen_src/chromium_impl/media/base/efl/webmediaplayer_efl.cc b/tizen_src/chromium_impl/media/base/efl/webmediaplayer_efl.cc index 22769dd..515be96 100644 --- a/tizen_src/chromium_impl/media/base/efl/webmediaplayer_efl.cc +++ b/tizen_src/chromium_impl/media/base/efl/webmediaplayer_efl.cc @@ -8,13 +8,13 @@ #include "cc/blink/web_layer_impl.h" #include "cc/layers/video_layer.h" -#include "content/common/wrt/wrt_url_parse.h" #include "content/renderer/media/render_media_log.h" #include "content/renderer/media/renderer_gpu_video_accelerator_factories.h" #include "content/renderer/render_frame_impl.h" #include "content/renderer/render_thread_impl.h" -#include "media/base/efl/media_player_efl.h" #include "media/base/bind_to_current_loop.h" +#include "media/base/efl/media_player_efl.h" +#include "media/base/efl/media_player_util_efl.h" #include "media/base/video_frame.h" #include "media/blink/webmediaplayer_util.h" #include "third_party/libyuv/include/libyuv/planar_functions.h" @@ -24,37 +24,25 @@ (DCHECK(main_loop_->BelongsToCurrentThread()), \ media::BindToCurrentLoop(base::Bind(function, AsWeakPtr()))) -namespace media { +namespace content { -// fourcc for gst-video-format -const uint32 GST_VIDEO_SN12 = GST_MAKE_FOURCC('S','N','1','2'); -const uint32 GST_VIDEO_I420 = GST_MAKE_FOURCC('I','4','2','0'); -const uint32 GST_VIDEO_NV12 = GST_MAKE_FOURCC('N','V','1','2'); - -// tile size for SN12 -const uint SN12_TILE_WIDTH = 64; -const uint SN12_TILE_HEIGHT = 32; -const uint SN12_TILE_SIZE = SN12_TILE_WIDTH * SN12_TILE_HEIGHT; - -// Removes query string from URI -GURL GetCleanURL(std::string url) { - // FIXME: Need to consider "app://" scheme. - if (!url.compare(0, 7, "file://")) { - int position = url.find("?"); - if(position != -1) - url.erase(url.begin() + position, url.end()); - } - GURL url_(url); - return url_; +blink::WebMediaPlayer* CreateWebMediaPlayerEfl( + content::RendererMediaPlayerManager* manager, + blink::WebFrame* frame, + blink::WebMediaPlayerClient* client, + base::WeakPtr delegate) { + return new media::WebMediaPlayerEfl(manager, frame, client, delegate); } +} // namespace content + +namespace media { + WebMediaPlayerEfl::WebMediaPlayerEfl( - content::RendererMediaPlayerManagerEfl* manager, - blink::WebLocalFrame* frame, + content::RendererMediaPlayerManager* manager, + blink::WebFrame* frame, blink::WebMediaPlayerClient* client, - base::WeakPtr delegate, - const WebMediaPlayerParams& params, - content::WrtUrlParseBase* wrt_url_parse) + base::WeakPtr delegate) : frame_(frame), network_state_(blink::WebMediaPlayer::NetworkStateEmpty), ready_state_(blink::WebMediaPlayer::ReadyStateHaveNothing), @@ -84,15 +72,16 @@ WebMediaPlayerEfl::WebMediaPlayerEfl( opaque_(false), natural_size_(0, 0), did_loading_progress_(false), - volume_(0), - gpu_factories_(content::RenderThreadImpl::current()->GetGpuFactories()), - encrypted_media_support_( - params.CreateEncryptedMediaPlayerSupport(client)), - wrt_url_parse_(wrt_url_parse) { + gpu_factories_(content::RenderThreadImpl::current()->GetGpuFactories()) +#if defined(TIZEN_MULTIMEDIA_EME_SUPPORT) + , encrypted_media_support_( + params.CreateEncryptedMediaPlayerSupport(client)) +#endif + { DCHECK(manager_); +#if defined(TIZEN_MULTIMEDIA_EME_SUPPORT) DCHECK(encrypted_media_support_); - VLOG(1) << "WebMediaPlayerEfl::" << __FUNCTION__; - FrameAvailable_ = false; +#endif // We want to be notified of |main_loop_| destruction. base::MessageLoop::current()->AddDestructionObserver(this); @@ -107,7 +96,6 @@ WebMediaPlayerEfl::WebMediaPlayerEfl( } WebMediaPlayerEfl::~WebMediaPlayerEfl() { - VLOG(1) << "WebMediaPlayerEfl::" << __FUNCTION__; if (manager_) { manager_->DestroyPlayer(player_id_); manager_->UnregisterMediaPlayer(player_id_); @@ -119,7 +107,7 @@ WebMediaPlayerEfl::~WebMediaPlayerEfl() { delegate_->PlayerGone(this); if (base::MessageLoop::current()) base::MessageLoop::current()->RemoveDestructionObserver(this); - compositor_task_runner_->DeleteSoon(FROM_HERE, compositor_); + compositor_task_runner_->DeleteSoon(FROM_HERE, compositor_); if (media_source_delegate_) { // Part of |media_source_delegate_| needs to be stopped // on the media thread. @@ -133,59 +121,47 @@ WebMediaPlayerEfl::~WebMediaPlayerEfl() { } void WebMediaPlayerEfl::load(LoadType load_type, - const blink::WebURL& url, - CORSMode cors_mode) { - VLOG(1) << "WebMediaPlayerEfl::" << __FUNCTION__ << " load type - " - << load_type; + const blink::WebURL& url, + CORSMode cors_mode) { int demuxer_client_id = 0; if (load_type == LoadTypeMediaSource) { - // FIXME: EFL GST-package on desktop cannot handle AAC decoding. + // EFL GST-package on desktop cannot handle AAC decoding. // Disabling MSE for desktop. -#ifdef OS_TIZEN player_type_ = MEDIA_PLAYER_TYPE_MEDIA_SOURCE; content::RendererDemuxerEfl* demuxer = - content::RenderThreadImpl::current()->renderer_demuxer(); + static_cast( + content::RenderThreadImpl::current()->renderer_demuxer()); demuxer_client_id = demuxer->GetNextDemuxerClientID(); media_source_delegate_.reset(new content::MediaSourceDelegateEfl( demuxer, demuxer_client_id, media_task_runner_, media_log_.get())); - SetDecryptorReadyCB set_decryptor_ready_cb = + SetDecryptorReadyCB set_decryptor_ready_cb; + Demuxer::EncryptedMediaInitDataCB emedia_init_data_cb; +#if defined(TIZEN_MULTIMEDIA_EME_SUPPORT) + set_decryptor_ready_cb = encrypted_media_support_->CreateSetDecryptorReadyCB(); - Demuxer::NeedKeyCB need_key_cb = + emedia_init_data_cb = encrypted_media_support_->CreateNeedKeyCB(); +#endif media_source_delegate_->InitializeMediaSource( base::Bind(&WebMediaPlayerEfl::OnMediaSourceOpened, weak_factory_.GetWeakPtr()), - need_key_cb, - set_decryptor_ready_cb, + emedia_init_data_cb, set_decryptor_ready_cb, base::Bind(&WebMediaPlayerEfl::SetNetworkState, weak_factory_.GetWeakPtr()), base::Bind(&WebMediaPlayerEfl::OnDurationChange, weak_factory_.GetWeakPtr())); -#else - // Posting Error Message to HTMLMediaElement. - SetNetworkState(WebMediaPlayer::NetworkStateDecodeError); -#endif } else if (load_type == LoadTypeURL) { player_type_ = MEDIA_PLAYER_TYPE_URL; } else { - LOG(ERROR) << "Unsupported load type " << load_type; + LOG(ERROR) << "Unsupported load type : " << load_type; return; } - blink::WebURL real_url; - if (wrt_url_parse_) - real_url = wrt_url_parse_->parseUrl(url); - else - real_url = url; - - // FIXME: Check URL, Volume for MS. - manager_->Initialize(player_id_, - player_type_, - GetCleanURL(real_url.string().utf8()), - volume_, - demuxer_client_id); + manager_->Initialize(player_id_, player_type_, + GetCleanURL(url.string().utf8()), 0, demuxer_client_id); } +#if defined(TIZEN_MULTIMEDIA_EME_SUPPORT) blink::WebMediaPlayer::MediaKeyException WebMediaPlayerEfl::generateKeyRequest(const blink::WebString& key_system, const unsigned char* init_data, @@ -231,9 +207,11 @@ void WebMediaPlayerEfl::setContentDecryptionModule( encrypted_media_support_->SetContentDecryptionModule(cdm, result); } +#endif void WebMediaPlayerEfl::OnMediaSourceOpened( blink::WebMediaSource* web_media_source) { + DCHECK(client_); client_->mediaSourceOpened(web_media_source); } @@ -252,8 +230,21 @@ void WebMediaPlayerEfl::pause() { } void WebMediaPlayerEfl::RequestPause() { - pause(); - client_->playbackStateChanged(); + switch (network_state_) { + // Pause the media player and inform Blink if the player is in a good + // shape. + case WebMediaPlayer::NetworkStateIdle: + case WebMediaPlayer::NetworkStateLoading: + case WebMediaPlayer::NetworkStateLoaded: + pause(); + client_->playbackStateChanged(); + break; + // If a WebMediaPlayer instance has entered into other then above states, + // the internal network state in HTMLMediaElement could be set to empty. + // And calling playbackStateChanged() could get this object deleted. + default: + break; + } } bool WebMediaPlayerEfl::supportsSave() const { @@ -261,8 +252,6 @@ bool WebMediaPlayerEfl::supportsSave() const { } void WebMediaPlayerEfl::seek(double seconds) { - VLOG(1) << "WebMediaPlayerEfl::" << __FUNCTION__ << " : " << seconds - << " ID " << player_id_; DCHECK(main_loop_->BelongsToCurrentThread()); if (is_seeking_) { @@ -314,11 +303,12 @@ void WebMediaPlayerEfl::setRate(double rate) { } void WebMediaPlayerEfl::setVolume(double volume) { - volume_ = volume; manager_->SetVolume(player_id_, volume); } -blink::WebTimeRanges WebMediaPlayerEfl::buffered() const{ +blink::WebTimeRanges WebMediaPlayerEfl::buffered() const { + if (media_source_delegate_) + return media_source_delegate_->Buffered(); return buffered_; } @@ -339,9 +329,10 @@ void WebMediaPlayerEfl::paint(blink::WebCanvas* canvas, GetCurrentFrameFromCompositor(); gfx::Rect gfx_rect(rect); + Context3D context_3d; skcanvas_video_renderer_.Paint( video_frame.get(), canvas, gfx_rect, alpha, - SkXfermode::kSrcOver_Mode, media::VIDEO_ROTATION_0); + SkXfermode::kSrcOver_Mode, media::VIDEO_ROTATION_0, context_3d); } bool WebMediaPlayerEfl::hasVideo() const { @@ -445,7 +436,10 @@ void WebMediaPlayerEfl::OnNewFrameAvailable(base::SharedMemoryHandle Handle, uint32 yuv_size, base::TimeDelta timestamp) { base::SharedMemory shared_memory(Handle, false); - shared_memory.Map(yuv_size); + if (!shared_memory.Map(yuv_size)) { + LOG(ERROR) << "Failed to map shared memory for size " << yuv_size; + return; + } uint8* const yuv_buffer = static_cast(shared_memory.memory()); gfx::Size size(gst_width_, gst_height_); @@ -456,7 +450,7 @@ void WebMediaPlayerEfl::OnNewFrameAvailable(base::SharedMemoryHandle Handle, // decoded format is SN12 on Tizen device // video format converted from SN12 to YV12 uint8* gst_buf = yuv_buffer; - switch(gst_video_format_) { + switch (gst_video_format_) { case GST_VIDEO_I420: { const uint c_frm_size = yuv_size / 6; const uint y_frm_size = c_frm_size << 2; // * 4; @@ -484,9 +478,6 @@ void WebMediaPlayerEfl::OnNewFrameAvailable(base::SharedMemoryHandle Handle, break; } case GST_VIDEO_SN12: { - //const uint tile_w = (gst_width_ - 1) / SN12_TILE_WIDTH + 1; - //const uint tile_w_align = (tile_w + 1) & ~1; - //const uint tile_h_luma = (gst_height_ - 1) / SN12_TILE_HEIGHT + 1; const uint tile_w_align = ((gst_width_ - 1) / SN12_TILE_WIDTH + 2) & ~1; const uint tile_luma_stride = tile_w_align * SN12_TILE_WIDTH; uint luma_size = SN12_TILE_SIZE * tile_w_align @@ -495,8 +486,8 @@ void WebMediaPlayerEfl::OnNewFrameAvailable(base::SharedMemoryHandle Handle, uint8* y_frm = video_frame.get()->data(VideoFrame::kYPlane); const uint y_stride = video_frame.get()->stride(VideoFrame::kYPlane); - // actually copy and convert luma buffer - for(int i=0; istride(VideoFrame::kUPlane); const uint uv_rows = video_frame.get()->rows(VideoFrame::kUPlane); - // actually copy and convert chroma buffer - for(uint row=0; rowdata(VideoFrame::kUPlane); uint8* v_plane = video_frame.get()->data(VideoFrame::kVPlane); - for(uint i = 0; i < c_frm_size; i++){ + for (uint i = 0; i < c_frm_size; i++) { // kUPlane u_plane[i] = gst_buf[i * 2]; // kVPlane @@ -551,14 +541,10 @@ void WebMediaPlayerEfl::OnNewFrameAvailable(base::SharedMemoryHandle Handle, break; } } - - shared_memory.Close(); FrameReady(video_frame); } #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT) -// FIXME: Graphics team need to merge painting of Video-Frame on to 2d-canvas -// from m34. void WebMediaPlayerEfl::OnPlatformSurfaceUpdated( int pixmap_id, base::TimeDelta timestamp) { @@ -578,7 +564,9 @@ void WebMediaPlayerEfl::FrameReady( base::Unretained(compositor_), frame)); } -void WebMediaPlayerEfl::OnMediaDataChange(int format, int height, int width, int media) { + +void WebMediaPlayerEfl::OnMediaDataChange(int format, int height, + int width, int media) { gst_video_format_ = static_cast(format); gst_height_ = height; gst_width_ = width; @@ -616,7 +604,6 @@ void WebMediaPlayerEfl::OnDurationChange(double duration) { void WebMediaPlayerEfl::OnNaturalSizeChanged(gfx::Size size) { DCHECK(main_loop_->BelongsToCurrentThread()); DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing); - TRACE_EVENT0("media", "WebMediaPlayerEfl::OnNaturalSizeChanged"); media_log_->AddEvent( media_log_->CreateVideoSizeSetEvent(size.width(), size.height())); natural_size_ = size; @@ -637,15 +624,12 @@ static void GetCurrentFrameAndSignal( media::VideoFrameCompositor* compositor, scoped_refptr* video_frame_out, base::WaitableEvent* event) { - TRACE_EVENT0("media", "GetCurrentFrameAndSignal"); *video_frame_out = compositor->GetCurrentFrame(); event->Signal(); } scoped_refptr - WebMediaPlayerEfl::GetCurrentFrameFromCompositor() { - TRACE_EVENT0("media", "WebMediaPlayerImpl::GetCurrentFrameFromCompositor"); - +WebMediaPlayerEfl::GetCurrentFrameFromCompositor() { if (compositor_task_runner_->BelongsToCurrentThread()) return compositor_->GetCurrentFrame(); @@ -656,8 +640,7 @@ scoped_refptr compositor_task_runner_->PostTask(FROM_HERE, base::Bind(&GetCurrentFrameAndSignal, base::Unretained(compositor_), - &video_frame, - &event)); + &video_frame, &event)); event.Wait(); return video_frame; } @@ -670,7 +653,7 @@ void WebMediaPlayerEfl::OnBufferUpdate( std::vector buffer_range) { media::Ranges time_ranges; std::vector::iterator tr_it; - for ( tr_it = buffer_range.begin(); tr_it != buffer_range.end(); ++tr_it) { + for (tr_it = buffer_range.begin(); tr_it != buffer_range.end(); ++tr_it) { time_ranges.Add( base::TimeDelta::FromMicroseconds((*tr_it).start), base::TimeDelta::FromMicroseconds((*tr_it).end)); @@ -681,19 +664,18 @@ void WebMediaPlayerEfl::OnBufferUpdate( } void WebMediaPlayerEfl::OnPauseStateChange(bool state) { - VLOG(1) << "WebMediaPlayerEfl::" << __FUNCTION__ << " state:" << state; is_paused_ = state; - if (delegate_.get()) { - if(is_paused_) - delegate_->DidPause(this); - else - delegate_->DidPlay(this); - } + client_->playbackStateChanged(); + if (!delegate_) + return; + + if(is_paused_) + delegate_->DidPause(this); + else + delegate_->DidPlay(this); } void WebMediaPlayerEfl::OnSeekStateChange(bool state) { - VLOG(1) << "WebMediaPlayerEfl::" << __FUNCTION__ << " state:" << state - << " ID " << player_id_; is_seeking_ = state; // Draw empty frame during seek. if (video_ && is_seeking_) { diff --git a/tizen_src/chromium_impl/media/base/efl/webmediaplayer_efl.h b/tizen_src/chromium_impl/media/base/efl/webmediaplayer_efl.h index d524d83..e47745b 100644 --- a/tizen_src/chromium_impl/media/base/efl/webmediaplayer_efl.h +++ b/tizen_src/chromium_impl/media/base/efl/webmediaplayer_efl.h @@ -2,19 +2,27 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_RENDERER_MEDIA_TIZEN_WEBMEDIAPLAYER_EFL_H_ -#define CONTENT_RENDERER_MEDIA_TIZEN_WEBMEDIAPLAYER_EFL_H_ +#ifndef MEDIA_BASE_EFL_WEBMEDIAPLAYER_EFL_H_ +#define MEDIA_BASE_EFL_WEBMEDIAPLAYER_EFL_H_ + +#include #include "base/message_loop/message_loop.h" +#include "base/memory/shared_memory.h" #include "cc/layers/video_frame_provider_client_impl.h" #include "content/renderer/media/efl/media_source_delegate_efl.h" #include "content/renderer/media/efl/renderer_media_player_manager_efl.h" #include "media/blink/video_frame_compositor.h" -#include "media/blink/webmediaplayer_params.h" #include "media/filters/skcanvas_video_renderer.h" +#include "third_party/WebKit/public/platform/WebMediaPlayer.h" + +#if defined(TIZEN_MULTIMEDIA_EME_SUPPORT) +#include "media/blink/encrypted_media_player_support.h" +#endif namespace blink { -class WebLocalFrame; +class WebFrame; +class WebMediaPlayerClient; } namespace cc_blink { @@ -22,16 +30,16 @@ class WebLayerImpl; } namespace content { -class RendererMediaPlayerManagerEfl; -class WrtUrlParseBase; +class RendererMediaPlayerManager; } namespace media { - class GpuVideoAcceleratorFactories; +class MediaLog; +class MediaPlayerEfl; class WebMediaPlayerDelegate; -// This class implements blink::WebMediaPlayer by keeping the tizen +// This class implements blink::WebMediaPlayer by keeping the efl // media player in the browser process. It listens to all the status changes // sent from the browser process and sends playback controls to the media // player. @@ -45,13 +53,11 @@ class WebMediaPlayerEfl // with the WebMediaPlayerEfl object in the browser process through // |proxy|. WebMediaPlayerEfl( - content::RendererMediaPlayerManagerEfl* manager, - blink::WebLocalFrame* frame, + content::RendererMediaPlayerManager* manager, + blink::WebFrame* frame, blink::WebMediaPlayerClient* client, - base::WeakPtr delegate, - const WebMediaPlayerParams& params, - content::WrtUrlParseBase* wrt_url_parse); - virtual ~WebMediaPlayerEfl(); + base::WeakPtr delegate); + ~WebMediaPlayerEfl() override; // blink::WebMediaPlayer implementation. void load(LoadType load_type, @@ -111,7 +117,7 @@ class WebMediaPlayerEfl // Method inherited from DestructionObserver. void WillDestroyCurrentMessageLoop() override {}; - +#if defined(TIZEN_MULTIMEDIA_EME_SUPPORT) virtual MediaKeyException generateKeyRequest( const blink::WebString& key_system, const unsigned char* init_data, @@ -135,6 +141,7 @@ class WebMediaPlayerEfl virtual void setContentDecryptionModule( blink::WebContentDecryptionModule* cdm, blink::WebContentDecryptionModuleResult result); +#endif void SetReadyState(WebMediaPlayer::ReadyState state); void SetNetworkState(WebMediaPlayer::NetworkState state); @@ -172,7 +179,7 @@ class WebMediaPlayerEfl // Called whenever there is new frame to be painted. void FrameReady(const scoped_refptr& frame); - blink::WebLocalFrame* frame_; + blink::WebFrame* frame_; blink::WebMediaPlayer::NetworkState network_state_; blink::WebMediaPlayer::ReadyState ready_state_; @@ -184,7 +191,7 @@ class WebMediaPlayerEfl // Manager for managing this object and for delegating method calls on // Render Thread. - content::RendererMediaPlayerManagerEfl* manager_; + content::RendererMediaPlayerManager* manager_; blink::WebMediaPlayerClient* client_; @@ -196,8 +203,7 @@ class WebMediaPlayerEfl // composited playback. scoped_ptr video_weblayer_; - - // Video rendering members. + // Video rendering members. scoped_refptr compositor_task_runner_; media::VideoFrameCompositor* compositor_; media::SkCanvasVideoRenderer skcanvas_video_renderer_; @@ -213,7 +219,6 @@ class WebMediaPlayerEfl int gst_width_; int gst_height_; - bool FrameAvailable_; bool audio_; bool video_; @@ -232,16 +237,16 @@ class WebMediaPlayerEfl gfx::Size natural_size_; blink::WebTimeRanges buffered_; mutable bool did_loading_progress_; - double volume_; // Factories for supporting video accelerators. May be null. scoped_refptr gpu_factories_; - scoped_ptr encrypted_media_support_; - content::WrtUrlParseBase* wrt_url_parse_; +#if defined(TIZEN_MULTIMEDIA_EME_SUPPORT) + scoped_ptr encrypted_media_support_; +#endif DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerEfl); }; } // namespace media -#endif // CONTENT_RENDERER_MEDIA_TIZEN_WEBMEDIAPLAYER_EFL_H_ +#endif // MEDIA_BASE_EFL_WEBMEDIAPLAYER_EFL_H_ \ No newline at end of file diff --git a/tizen_src/chromium_impl/media/media_efl.gypi b/tizen_src/chromium_impl/media/media_efl.gypi index a897f4c..f8713c8 100644 --- a/tizen_src/chromium_impl/media/media_efl.gypi +++ b/tizen_src/chromium_impl/media/media_efl.gypi @@ -30,10 +30,13 @@ 'base/efl/media_player_bridge_gstreamer.cc', 'base/efl/media_player_bridge_gstreamer.h', 'base/efl/media_player_manager_efl.h', + 'base/efl/media_player_util_efl.cc', + 'base/efl/media_player_util_efl.h', 'base/efl/media_source_player_gstreamer.cc', 'base/efl/media_source_player_gstreamer.h', 'base/efl/webmediaplayer_efl.cc', 'base/efl/webmediaplayer_efl.h', # ME and MSE + 'video/capture/tizen/video_capture_device_factory_tizen_helper.cc', # WebRTC ], 'conditions': [ @@ -53,7 +56,6 @@ 'video/capture/tizen/video_capture_device_tizen.h', 'video/capture/tizen/video_capture_device_factory_tizen.cc', 'video/capture/tizen/video_capture_device_factory_tizen.h', - 'video/capture/tizen/video_capture_device_factory_tizen_helper.cc', ], }], @@ -63,7 +65,11 @@ 'audio/tizen/audio_session_manager.cc', # ASM ], }], - + ['tizen_multimedia_eme_support==1', { + 'defines': [ + 'TIZEN_MULTIMEDIA_EME_SUPPORT=1', + ], + }], ['tizen_multimedia_use_capi_for_me==1', { 'defines': [ 'TIZEN_CAPI_PLAYER_SUPPORT=1', diff --git a/tizen_src/ewk/efl_integration/browser/render_message_filter_efl.cc b/tizen_src/ewk/efl_integration/browser/render_message_filter_efl.cc index 8479523..aeb6efd 100644 --- a/tizen_src/ewk/efl_integration/browser/render_message_filter_efl.cc +++ b/tizen_src/ewk/efl_integration/browser/render_message_filter_efl.cc @@ -22,15 +22,21 @@ using web_contents_utils::WebContentsFromViewID; using web_contents_utils::WebViewFromWebContents; using content::BrowserThread; +const uint32 kFilteredMessageClasses[] = { + EwkMsgStart, + ChromeMsgStart, +}; + RenderMessageFilterEfl::RenderMessageFilterEfl(int render_process_id) - : BrowserMessageFilter(EwkMsgStart) + : BrowserMessageFilter(kFilteredMessageClasses, + arraysize(kFilteredMessageClasses)) , render_process_id_(render_process_id) { } RenderMessageFilterEfl::~RenderMessageFilterEfl() { } -void RenderMessageFilterEfl::OverrideThreadForMessage(const IPC::Message& message, - content::BrowserThread::ID* thread) +void RenderMessageFilterEfl::OverrideThreadForMessage( + const IPC::Message& message, content::BrowserThread::ID* thread) { switch (message.type()) { case EwkHostMsg_DecideNavigationPolicy::ID: @@ -42,16 +48,19 @@ void RenderMessageFilterEfl::OverrideThreadForMessage(const IPC::Message& messag bool RenderMessageFilterEfl::OnMessageReceived(const IPC::Message& message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(RenderMessageFilterEfl, message) - IPC_MESSAGE_HANDLER(EwkHostMsg_DecideNavigationPolicy, OnDecideNavigationPolicy) + IPC_MESSAGE_HANDLER(EwkHostMsg_DecideNavigationPolicy, + OnDecideNavigationPolicy) #if defined(TIZEN_MULTIMEDIA_SUPPORT) - IPC_MESSAGE_HANDLER(EflViewHostMsg_GstWebAudioDecode, OnGstWebAudioDecode) + IPC_MESSAGE_HANDLER(EflViewHostMsg_GstWebAudioDecode, + OnGstWebAudioDecode) #endif IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; } -void RenderMessageFilterEfl::OnDecideNavigationPolicy(NavigationPolicyParams params, bool* handled) { +void RenderMessageFilterEfl::OnDecideNavigationPolicy( + NavigationPolicyParams params, bool* handled) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); if (content::WebContents* web_contents = @@ -66,7 +75,7 @@ void RenderMessageFilterEfl::OnGstWebAudioDecode( base::SharedMemoryHandle encoded_data_handle, base::FileDescriptor pcm_output, uint32_t data_size) { - content::BrowserMessageFilterEfl::GetInstance()->EncodedDataReceived( + content::WebAudioDecoderGStreamer::GetInstance()->EncodedDataReceived( encoded_data_handle, pcm_output, data_size); } #endif -- 2.7.4