diff options
Diffstat (limited to 'avmedia/source/gstreamer/gstplayer.cxx')
-rw-r--r-- | avmedia/source/gstreamer/gstplayer.cxx | 130 |
1 files changed, 86 insertions, 44 deletions
diff --git a/avmedia/source/gstreamer/gstplayer.cxx b/avmedia/source/gstreamer/gstplayer.cxx index 4efbc6497b09..1a91a689299e 100644 --- a/avmedia/source/gstreamer/gstplayer.cxx +++ b/avmedia/source/gstreamer/gstplayer.cxx @@ -25,10 +25,13 @@ #include <cstddef> #include <cstring> #include <map> +#include <mutex> #include <set> #include <vector> #include <math.h> +#include <com/sun/star/text/GraphicCrop.hpp> + #include <cppuhelper/supportsservice.hxx> #include <sal/log.hxx> #include <rtl/string.hxx> @@ -36,15 +39,14 @@ #include <vcl/svapp.hxx> #include <vcl/syschild.hxx> #include <vcl/sysdata.hxx> +#include <vcl/graph.hxx> +#include <avmedia/mediaitem.hxx> #include "gstplayer.hxx" #include "gstframegrabber.hxx" #include "gstwindow.hxx" #include <gst/video/videooverlay.h> -#define AVMEDIA_GST_PLAYER_IMPLEMENTATIONNAME "com.sun.star.comp.avmedia.Player_GStreamer" -#define AVMEDIA_GST_PLAYER_SERVICENAME "com.sun.star.media.Player_GStreamer" - #include <gst/pbutils/missing-plugins.h> #include <gst/pbutils/pbutils.h> @@ -95,7 +97,7 @@ private: DECL_STATIC_LINK(MissingPluginInstaller, launchUi, void*, void); - osl::Mutex mutex_; + std::recursive_mutex mutex_; std::set<OString> reported_; std::map<OString, std::set<rtl::Reference<Player>>> queued_; rtl::Reference<MissingPluginInstallerThread> currentThread_; @@ -107,7 +109,7 @@ private: MissingPluginInstaller::~MissingPluginInstaller() { - osl::MutexGuard g(mutex_); + std::unique_lock g(mutex_); SAL_WARN_IF(currentThread_.is(), "avmedia.gstreamer", "unjoined thread"); inCleanUp_ = true; } @@ -135,7 +137,7 @@ void MissingPluginInstaller::report( rtl::Reference<MissingPluginInstallerThread> join; rtl::Reference<MissingPluginInstallerThread> launch; { - osl::MutexGuard g(mutex_); + std::unique_lock g(mutex_); if (reported_.find(detStr) != reported_.end()) { return; } @@ -180,7 +182,7 @@ void eraseSource(std::set<rtl::Reference<Player>> & set, Player const * source) void MissingPluginInstaller::detach(Player const * source) { rtl::Reference<MissingPluginInstallerThread> join; { - osl::MutexGuard g(mutex_); + std::unique_lock g(mutex_); if (inCleanUp_) { // Guard against ~MissingPluginInstaller with erroneously un-joined // currentThread_ (thus non-empty currentSources_) calling @@ -242,17 +244,19 @@ IMPL_STATIC_LINK(MissingPluginInstaller, launchUi, void *, p, void) } -struct TheMissingPluginInstaller: - public rtl::Static<MissingPluginInstaller, TheMissingPluginInstaller> -{}; +MissingPluginInstaller& TheMissingPluginInstaller() +{ + static MissingPluginInstaller theInstaller; + return theInstaller; +} void MissingPluginInstallerThread::execute() { - MissingPluginInstaller & inst = TheMissingPluginInstaller::get(); + MissingPluginInstaller & inst = TheMissingPluginInstaller(); for (;;) { std::vector<OString> details; { - osl::MutexGuard g(inst.mutex_); + std::unique_lock g(inst.mutex_); assert(!inst.currentDetails_.empty()); details.swap(inst.currentDetails_); } @@ -265,7 +269,7 @@ void MissingPluginInstallerThread::execute() { args.push_back(nullptr); gst_install_plugins_sync(args.data(), nullptr); { - osl::MutexGuard g(inst.mutex_); + std::unique_lock g(inst.mutex_); if (inst.queued_.empty() || inst.launchNewThread_) { inst.launchNewThread_ = true; break; @@ -285,7 +289,6 @@ Player::Player() : mbUseGtkSink( false ), mbFakeVideo (false ), mnUnmutedVolume( 0 ), - mbPlayPending ( false ), mbMuted( false ), mbLooping( false ), mbInitialized( false ), @@ -328,7 +331,7 @@ Player::~Player() void SAL_CALL Player::disposing() { - TheMissingPluginInstaller::get().detach(this); + TheMissingPluginInstaller().detach(this); ::osl::MutexGuard aGuard(m_aMutex); @@ -385,7 +388,6 @@ void Player::processMessage( GstMessage *message ) switch( GST_MESSAGE_TYPE( message ) ) { case GST_MESSAGE_EOS: gst_element_set_state( mpPlaybin, GST_STATE_READY ); - mbPlayPending = false; if (mbLooping) start(); break; @@ -401,9 +403,6 @@ void Player::processMessage( GstMessage *message ) { gst_video_overlay_expose(mpXOverlay); } - - if (mbPlayPending) - mbPlayPending = ((newstate == GST_STATE_READY) || (newstate == GST_STATE_PAUSED)); } break; default: @@ -447,6 +446,28 @@ GstBusSyncReply Player::processSyncMessage( GstMessage *message ) "error: '" << error->message << "' debug: '" << error_debug << "'"); } + else if ( GST_MESSAGE_TYPE( message ) == GST_MESSAGE_WARNING ) + { + GError* error; + gchar* error_debug; + + gst_message_parse_warning( message, &error, &error_debug ); + SAL_WARN( + "avmedia.gstreamer", + "warning: '" << error->message << "' debug: '" + << error_debug << "'"); + } + else if ( GST_MESSAGE_TYPE( message ) == GST_MESSAGE_INFO ) + { + GError* error; + gchar* error_debug; + + gst_message_parse_info( message, &error, &error_debug ); + SAL_WARN( + "avmedia.gstreamer", + "info: '" << error->message << "' debug: '" + << error_debug << "'"); + } #endif if (!mbUseGtkSink) @@ -512,7 +533,7 @@ GstBusSyncReply Player::processSyncMessage( GstMessage *message ) maSizeCondition.set(); } } else if (gst_is_missing_plugin_message(message)) { - TheMissingPluginInstaller::get().report(this, message); + TheMissingPluginInstaller().report(this, message); if( mnWidth == 0 ) { // an error occurred, set condition so that OOo thread doesn't wait for us maSizeCondition.set(); @@ -532,7 +553,6 @@ void Player::preparePlaybin( std::u16string_view rURL, GstElement *pSink ) if (mpPlaybin != nullptr) { gst_element_set_state( mpPlaybin, GST_STATE_NULL ); - mbPlayPending = false; g_object_unref( mpPlaybin ); } @@ -597,7 +617,6 @@ bool Player::create( const OUString& rURL ) preparePlaybin( rURL, gst_element_factory_make( "fakesink", nullptr ) ); gst_element_set_state( mpPlaybin, GST_STATE_PAUSED ); - mbPlayPending = false; bRet = true; } @@ -610,7 +629,6 @@ bool Player::create( const OUString& rURL ) return bRet; } - void SAL_CALL Player::start() { ::osl::MutexGuard aGuard(m_aMutex); @@ -619,10 +637,10 @@ void SAL_CALL Player::start() if( mbInitialized && mpPlaybin != nullptr ) { gst_element_set_state( mpPlaybin, GST_STATE_PLAYING ); - mbPlayPending = true; } -} + SAL_INFO( "avmedia.gstreamer", AVVERSION "start " << mpPlaybin ); +} void SAL_CALL Player::stop() { @@ -632,29 +650,24 @@ void SAL_CALL Player::stop() if( mpPlaybin ) gst_element_set_state( mpPlaybin, GST_STATE_PAUSED ); - mbPlayPending = false; SAL_INFO( "avmedia.gstreamer", AVVERSION "stop " << mpPlaybin ); } - sal_Bool SAL_CALL Player::isPlaying() { ::osl::MutexGuard aGuard(m_aMutex); - bool bRet = mbPlayPending; + bool bRet = false; - // return whether the pipeline is in PLAYING STATE or not - if( !mbPlayPending && mbInitialized && mpPlaybin ) + // return whether the pipeline target is PLAYING STATE or not + if (mbInitialized && mpPlaybin) { - bRet = GST_STATE( mpPlaybin ) == GST_STATE_PLAYING; + bRet = GST_STATE_TARGET(mpPlaybin) == GST_STATE_PLAYING; } - SAL_INFO( "avmedia.gstreamer", AVVERSION "isPlaying " << bRet ); - return bRet; } - double SAL_CALL Player::getDuration() { ::osl::MutexGuard aGuard(m_aMutex); @@ -850,7 +863,7 @@ uno::Reference< ::media::XPlayerWindow > SAL_CALL Player::createPlayerWindow( co // tdf#124027: the position of embedded window is identical w/ the position // of media object in all other vclplugs (kf5, gen), in gtk3 w/o gtksink it // needs to be translated - if (pEnvData->toolkit == SystemEnvData::Toolkit::Gtk3) + if (pEnvData->toolkit == SystemEnvData::Toolkit::Gtk) { Point aPoint = pParentWindow->GetPosPixel(); maArea.X = aPoint.getX(); @@ -862,7 +875,7 @@ uno::Reference< ::media::XPlayerWindow > SAL_CALL Player::createPlayerWindow( co GstElement *pVideosink = static_cast<GstElement*>(pParentWindow->CreateGStreamerSink()); if (pVideosink) { - if (pEnvData->toolkit == SystemEnvData::Toolkit::Gtk3) + if (pEnvData->toolkit == SystemEnvData::Toolkit::Gtk) mbUseGtkSink = true; } else @@ -880,11 +893,40 @@ uno::Reference< ::media::XPlayerWindow > SAL_CALL Player::createPlayerWindow( co g_object_set(G_OBJECT(mpPlaybin), "video-sink", pVideosink, nullptr); g_object_set(G_OBJECT(mpPlaybin), "force-aspect-ratio", FALSE, nullptr); - mnWindowID = pEnvData->aWindow; - mpDisplay = pEnvData->pDisplay; - SAL_INFO( "avmedia.gstreamer", AVVERSION "set window id to " << static_cast<int>(mnWindowID) << " XOverlay " << mpXOverlay); + if ((rArguments.getLength() >= 4) && (rArguments[3] >>= pIntPtr) && pIntPtr) + { + auto pItem = reinterpret_cast<const avmedia::MediaItem*>(pIntPtr); + Graphic aGraphic = pItem->getGraphic(); + const text::GraphicCrop& rCrop = pItem->getCrop(); + if (!aGraphic.IsNone() && (rCrop.Bottom > 0 || rCrop.Left > 0 || rCrop.Right > 0 || rCrop.Top > 0)) + { + // The media item has a non-empty cropping set. Try to crop the video accordingly. + Size aPref = aGraphic.GetPrefSize(); + Size aPixel = aGraphic.GetSizePixel(); + tools::Long nLeft = aPixel.getWidth() * rCrop.Left / aPref.getWidth(); + tools::Long nTop = aPixel.getHeight() * rCrop.Top / aPref.getHeight(); + tools::Long nRight = aPixel.getWidth() * rCrop.Right / aPref.getWidth(); + tools::Long nBottom = aPixel.getHeight() * rCrop.Bottom / aPref.getHeight(); + GstElement* pVideoFilter = gst_element_factory_make("videocrop", nullptr); + if (pVideoFilter) + { + g_object_set(G_OBJECT(pVideoFilter), "left", nLeft, nullptr); + g_object_set(G_OBJECT(pVideoFilter), "top", nTop, nullptr); + g_object_set(G_OBJECT(pVideoFilter), "right", nRight, nullptr); + g_object_set(G_OBJECT(pVideoFilter), "bottom", nBottom, nullptr); + g_object_set(G_OBJECT(mpPlaybin), "video-filter", pVideoFilter, nullptr); + } + } + } + + if (!mbUseGtkSink) + { + mnWindowID = pEnvData->GetWindowHandle(pParentWindow->ImplGetFrame()); + mpDisplay = pEnvData->pDisplay; + SAL_INFO( "avmedia.gstreamer", AVVERSION "set window id to " << static_cast<int>(mnWindowID) << " XOverlay " << mpXOverlay); + } gst_element_set_state( mpPlaybin, GST_STATE_PAUSED ); - if ( mpXOverlay != nullptr ) + if (!mbUseGtkSink && mpXOverlay) gst_video_overlay_set_window_handle( mpXOverlay, mnWindowID ); } @@ -894,12 +936,12 @@ uno::Reference< ::media::XPlayerWindow > SAL_CALL Player::createPlayerWindow( co uno::Reference< media::XFrameGrabber > SAL_CALL Player::createFrameGrabber() { ::osl::MutexGuard aGuard(m_aMutex); - FrameGrabber* pFrameGrabber = nullptr; + rtl::Reference<FrameGrabber> pFrameGrabber; const awt::Size aPrefSize( getPreferredPlayerWindowSize() ); if( ( aPrefSize.Width > 0 ) && ( aPrefSize.Height > 0 ) ) pFrameGrabber = FrameGrabber::create( maURL ); - SAL_INFO( "avmedia.gstreamer", AVVERSION "created FrameGrabber " << pFrameGrabber ); + SAL_INFO( "avmedia.gstreamer", AVVERSION "created FrameGrabber " << pFrameGrabber.get() ); return pFrameGrabber; } @@ -907,7 +949,7 @@ uno::Reference< media::XFrameGrabber > SAL_CALL Player::createFrameGrabber() OUString SAL_CALL Player::getImplementationName() { - return AVMEDIA_GST_PLAYER_IMPLEMENTATIONNAME; + return u"com.sun.star.comp.avmedia.Player_GStreamer"_ustr; } @@ -919,7 +961,7 @@ sal_Bool SAL_CALL Player::supportsService( const OUString& ServiceName ) uno::Sequence< OUString > SAL_CALL Player::getSupportedServiceNames() { - return { AVMEDIA_GST_PLAYER_SERVICENAME }; + return { u"com.sun.star.media.Player_GStreamer"_ustr }; } } // namespace |