diff options
Diffstat (limited to 'avmedia/source/gstreamer')
-rw-r--r-- | avmedia/source/gstreamer/gstframegrabber.cxx | 26 | ||||
-rw-r--r-- | avmedia/source/gstreamer/gstframegrabber.hxx | 3 | ||||
-rw-r--r-- | avmedia/source/gstreamer/gstmanager.cxx | 10 | ||||
-rw-r--r-- | avmedia/source/gstreamer/gstplayer.cxx | 130 | ||||
-rw-r--r-- | avmedia/source/gstreamer/gstplayer.hxx | 1 | ||||
-rw-r--r-- | avmedia/source/gstreamer/gstwindow.cxx | 5 | ||||
-rw-r--r-- | avmedia/source/gstreamer/gstwindow.hxx | 2 |
7 files changed, 110 insertions, 67 deletions
diff --git a/avmedia/source/gstreamer/gstframegrabber.cxx b/avmedia/source/gstreamer/gstframegrabber.cxx index c1341d8d6ad4..d8f96bd5e568 100644 --- a/avmedia/source/gstreamer/gstframegrabber.cxx +++ b/avmedia/source/gstreamer/gstframegrabber.cxx @@ -31,8 +31,7 @@ #include <string> -#define AVMEDIA_GST_FRAMEGRABBER_IMPLEMENTATIONNAME "com.sun.star.comp.avmedia.FrameGrabber_GStreamer" -#define AVMEDIA_GST_FRAMEGRABBER_SERVICENAME "com.sun.star.media.FrameGrabber_GStreamer" +constexpr OUString AVMEDIA_GST_FRAMEGRABBER_SERVICENAME = u"com.sun.star.media.FrameGrabber_GStreamer"_ustr; using namespace ::com::sun::star; @@ -48,14 +47,11 @@ void FrameGrabber::disposePipeline() } } -FrameGrabber::FrameGrabber( std::u16string_view rURL ) : - FrameGrabber_BASE() +FrameGrabber::FrameGrabber( std::u16string_view rURL ) { - gchar *pPipelineStr; - pPipelineStr = g_strdup_printf( - "uridecodebin uri=%s ! videoconvert ! videoscale ! appsink " - "name=sink caps=\"video/x-raw,format=RGB,pixel-aspect-ratio=1/1\"", - OUStringToOString( rURL, RTL_TEXTENCODING_UTF8 ).getStr() ); + const char pPipelineStr[] = + "uridecodebin name=source ! videoconvert ! videoscale ! appsink " + "name=sink caps=\"video/x-raw,format=RGB,pixel-aspect-ratio=1/1\""; GError *pError = nullptr; mpPipeline = gst_parse_launch( pPipelineStr, &pError ); @@ -66,6 +62,12 @@ FrameGrabber::FrameGrabber( std::u16string_view rURL ) : } if( mpPipeline ) { + + if (GstElement *pUriDecode = gst_bin_get_by_name(GST_BIN(mpPipeline), "source")) + g_object_set(pUriDecode, "uri", OUStringToOString(rURL, RTL_TEXTENCODING_UTF8).getStr(), nullptr); + else + g_warning("Missing 'source' element in gstreamer pipeline"); + // pre-roll switch( gst_element_set_state( mpPipeline, GST_STATE_PAUSED ) ) { case GST_STATE_CHANGE_FAILURE: @@ -87,7 +89,7 @@ FrameGrabber::~FrameGrabber() disposePipeline(); } -FrameGrabber* FrameGrabber::create( std::u16string_view rURL ) +rtl::Reference<FrameGrabber> FrameGrabber::create( std::u16string_view rURL ) { return new FrameGrabber( rURL ); } @@ -147,7 +149,7 @@ uno::Reference< graphic::XGraphic > SAL_CALL FrameGrabber::grabFrame( double fMe pData = aMapInfo.data; int nStride = GST_ROUND_UP_4( nWidth * 3 ); - BitmapEx aBmp = vcl::bitmap::CreateFromData(pData, nWidth, nHeight, nStride, 24 ); + BitmapEx aBmp = vcl::bitmap::CreateFromData(pData, nWidth, nHeight, nStride, /*nBitsPerPixel*/24); gst_buffer_unmap( pBuf, &aMapInfo ); xRet = Graphic( aBmp ).GetXGraphic(); @@ -158,7 +160,7 @@ uno::Reference< graphic::XGraphic > SAL_CALL FrameGrabber::grabFrame( double fMe OUString SAL_CALL FrameGrabber::getImplementationName( ) { - return AVMEDIA_GST_FRAMEGRABBER_IMPLEMENTATIONNAME; + return u"com.sun.star.comp.avmedia.FrameGrabber_GStreamer"_ustr; } sal_Bool SAL_CALL FrameGrabber::supportsService( const OUString& ServiceName ) diff --git a/avmedia/source/gstreamer/gstframegrabber.hxx b/avmedia/source/gstreamer/gstframegrabber.hxx index b99401526506..c706192efd7d 100644 --- a/avmedia/source/gstreamer/gstframegrabber.hxx +++ b/avmedia/source/gstreamer/gstframegrabber.hxx @@ -26,6 +26,7 @@ #include "gstplayer.hxx" #include <com/sun/star/media/XFrameGrabber.hpp> #include <cppuhelper/implbase.hxx> +#include <rtl/ref.hxx> namespace avmedia::gstreamer { @@ -43,7 +44,7 @@ public: const FrameGrabber& operator=(const FrameGrabber&) =delete; // static create method instead of public Ctor - static FrameGrabber* create( std::u16string_view rURL ); + static rtl::Reference<FrameGrabber> create( std::u16string_view rURL ); virtual ~FrameGrabber() override; diff --git a/avmedia/source/gstreamer/gstmanager.cxx b/avmedia/source/gstreamer/gstmanager.cxx index bc7c917dc99d..54d23541676e 100644 --- a/avmedia/source/gstreamer/gstmanager.cxx +++ b/avmedia/source/gstreamer/gstmanager.cxx @@ -23,6 +23,7 @@ #include "gstplayer.hxx" #include <tools/urlobj.hxx> +#include <rtl/ref.hxx> using namespace ::com::sun::star; @@ -38,19 +39,18 @@ Manager::~Manager() uno::Reference< media::XPlayer > SAL_CALL Manager::createPlayer( const OUString& rURL ) { - Player* pPlayer( new Player ); - uno::Reference< media::XPlayer > xRet( pPlayer ); + rtl::Reference<Player> pPlayer( new Player ); const INetURLObject aURL( rURL ); if( !pPlayer->create( aURL.GetMainURL( INetURLObject::DecodeMechanism::Unambiguous ) ) ) - xRet.clear(); + pPlayer.clear(); - return xRet; + return pPlayer; } OUString SAL_CALL Manager::getImplementationName( ) { - return "com.sun.star.comp.avmedia.Manager_GStreamer"; + return "com.sun.star.comp.media.Manager_GStreamer"; } sal_Bool SAL_CALL Manager::supportsService( const OUString& ServiceName ) 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 diff --git a/avmedia/source/gstreamer/gstplayer.hxx b/avmedia/source/gstreamer/gstplayer.hxx index a82dac3f2b39..2694ac00ce7e 100644 --- a/avmedia/source/gstreamer/gstplayer.hxx +++ b/avmedia/source/gstreamer/gstplayer.hxx @@ -86,7 +86,6 @@ private: bool mbFakeVideo; gdouble mnUnmutedVolume; - bool mbPlayPending; bool mbMuted; bool mbLooping; bool mbInitialized; diff --git a/avmedia/source/gstreamer/gstwindow.cxx b/avmedia/source/gstreamer/gstwindow.cxx index 61f1b6a4cb61..2d9aec0418b3 100644 --- a/avmedia/source/gstreamer/gstwindow.cxx +++ b/avmedia/source/gstreamer/gstwindow.cxx @@ -22,10 +22,9 @@ #include <cppuhelper/supportsservice.hxx> #include "gstwindow.hxx" -#include "gstplayer.hxx" -#define AVMEDIA_GST_WINDOW_IMPLEMENTATIONNAME "com.sun.star.comp.avmedia.Window_GStreamer" -#define AVMEDIA_GST_WINDOW_SERVICENAME "com.sun.star.media.Window_GStreamer" +constexpr OUString AVMEDIA_GST_WINDOW_IMPLEMENTATIONNAME = u"com.sun.star.comp.avmedia.Window_GStreamer"_ustr; +constexpr OUString AVMEDIA_GST_WINDOW_SERVICENAME = u"com.sun.star.media.Window_GStreamer"_ustr; using namespace ::com::sun::star; diff --git a/avmedia/source/gstreamer/gstwindow.hxx b/avmedia/source/gstreamer/gstwindow.hxx index c9d633d5434f..ff8a7cc91566 100644 --- a/avmedia/source/gstreamer/gstwindow.hxx +++ b/avmedia/source/gstreamer/gstwindow.hxx @@ -19,10 +19,10 @@ #pragma once -#include "gstcommon.hxx" #include <cppuhelper/implbase.hxx> #include <cppuhelper/interfacecontainer.h> +#include <com/sun/star/lang/XServiceInfo.hpp> #include <com/sun/star/media/XPlayerWindow.hpp> namespace avmedia::gstreamer { |