summaryrefslogtreecommitdiff
path: root/avmedia/source/gstreamer/gstplayer.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'avmedia/source/gstreamer/gstplayer.cxx')
-rw-r--r--avmedia/source/gstreamer/gstplayer.cxx130
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