gtk3+wayland: play video via gtksink gstreamer element

Change-Id: Ib371fa06eda73962cbe94739e69a68b46c26e4bf
This commit is contained in:
Caolán McNamara
2016-02-16 16:01:02 +00:00
parent 3cdb86054c
commit 8543fbc72f
8 changed files with 137 additions and 69 deletions

View File

@@ -16,7 +16,21 @@ $(eval $(call gb_Library_set_include,avmediagst,\
-I$(SRCDIR)/avmedia/source/inc \
$(GSTREAMER_1_0_CFLAGS) \
))
$(eval $(call gb_Library_add_libs,avmediagst,$(GSTREAMER_1_0_LIBS)))
$(eval $(call gb_Library_add_libs,avmediagst,\
$(GSTREAMER_1_0_LIBS) \
))
ifneq ($(ENABLE_GTK3),)
$(eval $(call gb_Library_add_cxxflags,avmediagst,\
$$(GTK3_CFLAGS) \
-DENABLE_GTKSINK \
))
$(eval $(call gb_Library_add_libs,avmediagst,\
$(GTK3_LIBS) \
))
endif
$(eval $(call gb_Library_use_external,avmediagst,boost_headers))

View File

@@ -288,6 +288,10 @@ void MissingPluginInstallerThread::execute() {
Player::Player() :
GstPlayer_BASE( m_aMutex ),
mpPlaybin( nullptr ),
#if defined(ENABLE_GTKSINK)
mpGtkWidget( nullptr ),
#endif
mbUseGtkSink( false ),
mbFakeVideo (false ),
mnUnmutedVolume( 0 ),
mbPlayPending ( false ),
@@ -343,6 +347,14 @@ void SAL_CALL Player::disposing()
// Release the elements and pipeline
if( mbInitialized )
{
#if defined(ENABLE_GTKSINK)
if (mpGtkWidget)
{
gtk_widget_destroy(mpGtkWidget);
mpGtkWidget = nullptr;
}
#endif
if( mpPlaybin )
{
gst_element_set_state( mpPlaybin, GST_STATE_NULL );
@@ -393,18 +405,20 @@ void Player::processMessage( GstMessage *message )
start();
break;
case GST_MESSAGE_STATE_CHANGED:
if( message->src == GST_OBJECT( mpPlaybin ) ) {
if (message->src == GST_OBJECT(mpPlaybin))
{
GstState newstate, pendingstate;
gst_message_parse_state_changed (message, nullptr, &newstate, &pendingstate);
if( newstate == GST_STATE_PAUSED &&
pendingstate == GST_STATE_VOID_PENDING &&
mpXOverlay )
gst_video_overlay_expose( mpXOverlay );
if (!mbUseGtkSink && newstate == GST_STATE_PAUSED &&
pendingstate == GST_STATE_VOID_PENDING && mpXOverlay)
{
gst_video_overlay_expose(mpXOverlay);
}
if (mbPlayPending)
mbPlayPending = ((newstate == GST_STATE_READY) || (newstate == GST_STATE_PAUSED));
if (mbPlayPending)
mbPlayPending = ((newstate == GST_STATE_READY) || (newstate == GST_STATE_PAUSED));
}
default:
break;
@@ -450,23 +464,26 @@ GstBusSyncReply Player::processSyncMessage( GstMessage *message )
}
#endif
#ifdef AVMEDIA_GST_0_10
if (message->structure &&
!strcmp( gst_structure_get_name( message->structure ), "prepare-xwindow-id" ) )
#else
if (gst_is_video_overlay_prepare_window_handle_message (message) )
#endif
if (!mbUseGtkSink)
{
SAL_INFO( "avmedia.gstreamer", AVVERSION << this << " processSyncMessage prepare window id: " <<
GST_MESSAGE_TYPE_NAME( message ) << " " << (int)mnWindowID );
if( mpXOverlay )
g_object_unref( G_OBJECT ( mpXOverlay ) );
g_object_set( GST_MESSAGE_SRC( message ), "force-aspect-ratio", FALSE, nullptr );
mpXOverlay = GST_VIDEO_OVERLAY( GST_MESSAGE_SRC( message ) );
g_object_ref( G_OBJECT ( mpXOverlay ) );
if ( mnWindowID != 0 )
gst_video_overlay_set_window_handle( mpXOverlay, mnWindowID );
return GST_BUS_DROP;
#ifdef AVMEDIA_GST_0_10
if (message->structure &&
!strcmp( gst_structure_get_name( message->structure ), "prepare-xwindow-id" ) )
#else
if (gst_is_video_overlay_prepare_window_handle_message (message) )
#endif
{
SAL_INFO( "avmedia.gstreamer", AVVERSION << this << " processSyncMessage prepare window id: " <<
GST_MESSAGE_TYPE_NAME( message ) << " " << (int)mnWindowID );
if( mpXOverlay )
g_object_unref( G_OBJECT ( mpXOverlay ) );
g_object_set( GST_MESSAGE_SRC( message ), "force-aspect-ratio", FALSE, nullptr );
mpXOverlay = GST_VIDEO_OVERLAY( GST_MESSAGE_SRC( message ) );
g_object_ref( G_OBJECT ( mpXOverlay ) );
if ( mnWindowID != 0 )
gst_video_overlay_set_window_handle( mpXOverlay, mnWindowID );
return GST_BUS_DROP;
}
}
#ifdef AVMEDIA_GST_0_10
@@ -573,44 +590,50 @@ GstBusSyncReply Player::processSyncMessage( GstMessage *message )
return GST_BUS_PASS;
}
void Player::preparePlaybin( const OUString& rURL, GstElement *pSink )
{
GstBus *pBus;
if( mpPlaybin != nullptr ) {
gst_element_set_state( mpPlaybin, GST_STATE_NULL );
mbPlayPending = false;
g_object_unref( mpPlaybin );
}
mpPlaybin = gst_element_factory_make( "playbin", nullptr );
if( pSink != nullptr ) // used for getting preferred size etc.
{
g_object_set( G_OBJECT( mpPlaybin ), "video-sink", pSink, nullptr );
mbFakeVideo = true;
}
else
mbFakeVideo = false;
OString ascURL = OUStringToOString( rURL, RTL_TEXTENCODING_UTF8 );
g_object_set( G_OBJECT( mpPlaybin ), "uri", ascURL.getStr() , nullptr );
pBus = gst_element_get_bus( mpPlaybin );
if (mbWatchID)
{
g_source_remove(mnWatchID);
mbWatchID = false;
}
mnWatchID = gst_bus_add_watch( pBus, pipeline_bus_callback, this );
mbWatchID = true;
SAL_INFO( "avmedia.gstreamer", AVVERSION << this << " set sync handler" );
#ifdef AVMEDIA_GST_0_10
gst_bus_set_sync_handler( pBus, pipeline_bus_sync_handler, this );
#else
gst_bus_set_sync_handler( pBus, pipeline_bus_sync_handler, this, nullptr );
#if defined(ENABLE_GTKSINK)
if (mpGtkWidget)
{
gtk_widget_destroy(mpGtkWidget);
mpGtkWidget = nullptr;
}
#endif
g_object_unref( pBus );
if (mpPlaybin != nullptr)
{
gst_element_set_state( mpPlaybin, GST_STATE_NULL );
mbPlayPending = false;
g_object_unref( mpPlaybin );
}
mpPlaybin = gst_element_factory_make( "playbin", nullptr );
if( pSink != nullptr ) // used for getting preferred size etc.
{
g_object_set( G_OBJECT( mpPlaybin ), "video-sink", pSink, nullptr );
mbFakeVideo = true;
}
else
mbFakeVideo = false;
OString ascURL = OUStringToOString( rURL, RTL_TEXTENCODING_UTF8 );
g_object_set( G_OBJECT( mpPlaybin ), "uri", ascURL.getStr() , nullptr );
GstBus *pBus = gst_element_get_bus( mpPlaybin );
if (mbWatchID)
{
g_source_remove(mnWatchID);
mbWatchID = false;
}
mnWatchID = gst_bus_add_watch( pBus, pipeline_bus_callback, this );
mbWatchID = true;
SAL_INFO( "avmedia.gstreamer", AVVERSION << this << " set sync handler" );
#ifdef AVMEDIA_GST_0_10
gst_bus_set_sync_handler( pBus, pipeline_bus_sync_handler, this );
#else
gst_bus_set_sync_handler( pBus, pipeline_bus_sync_handler, this, nullptr );
#endif
g_object_unref( pBus );
}
@@ -886,11 +909,32 @@ uno::Reference< ::media::XPlayerWindow > SAL_CALL Player::createPlayerWindow( co
OSL_ASSERT(pEnvData);
if (pEnvData)
{
mnWindowID = pEnvData->aWindow;
SAL_INFO( "avmedia.gstreamer", AVVERSION "set window id to " << (int)mnWindowID << " XOverlay " << mpXOverlay);
gst_element_set_state( mpPlaybin, GST_STATE_PAUSED );
if ( mpXOverlay != nullptr )
gst_video_overlay_set_window_handle( mpXOverlay, mnWindowID );
#if defined(ENABLE_GTKSINK)
GstElement *pVideosink = g_strcmp0(pEnvData->pToolkit, "gtk3") == 0 ?
gst_element_factory_make("gtksink", "gtksink") : nullptr;
if (pVideosink)
{
mbUseGtkSink = true;
g_object_get(pVideosink, "widget", &mpGtkWidget, nullptr);
GtkWidget *pParent = (GtkWidget*)(pEnvData->pWidget);
gtk_container_add (GTK_CONTAINER(pParent), mpGtkWidget);
g_object_set( G_OBJECT( mpPlaybin ), "video-sink", pVideosink, nullptr);
g_object_set( G_OBJECT( mpPlaybin ), "force-aspect-ratio", FALSE, nullptr);
gtk_widget_show_all (pParent);
}
else
#endif
{
mbUseGtkSink = false;
mnWindowID = pEnvData->aWindow;
SAL_INFO( "avmedia.gstreamer", AVVERSION "set window id to " << (int)mnWindowID << " XOverlay " << mpXOverlay);
gst_element_set_state( mpPlaybin, GST_STATE_PAUSED );
if ( mpXOverlay != nullptr )
gst_video_overlay_set_window_handle( mpXOverlay, mnWindowID );
}
}
}
}

View File

@@ -27,6 +27,10 @@
#include <cppuhelper/compbase.hxx>
#include <cppuhelper/basemutex.hxx>
#if defined(ENABLE_GTKSINK)
# include <gtk/gtk.h>
#endif
typedef struct _GstVideoOverlay GstVideoOverlay;
namespace avmedia { namespace gstreamer {
@@ -78,6 +82,10 @@ protected:
// Add elements and pipeline here
GstElement* mpPlaybin; // the playbin is also a pipeline
#if defined(ENABLE_GTKSINK)
GtkWidget* mpGtkWidget;
#endif
bool mbUseGtkSink;
bool mbFakeVideo;
gdouble mnUnmutedVolume;

View File

@@ -72,6 +72,7 @@ struct SystemEnvData
void* pAppContext; // the application context in use
long aShellWindow; // the window of the frame's shell
void* pShellWidget; // the frame's shell widget
const char* pToolkit; // the toolkit in use (gtk2 vs gtk3)
#endif
SystemEnvData()
@@ -95,6 +96,7 @@ struct SystemEnvData
, pAppContext(nullptr)
, aShellWindow(0)
, pShellWidget(nullptr)
, pToolkit(nullptr)
#endif
{
}

View File

@@ -63,6 +63,7 @@ GtkSalObject::GtkSalObject( GtkSalFrame* pParent, bool bShow )
m_aSystemData.nScreen = pParent->getXScreenNumber().getXScreen();
m_aSystemData.pAppContext = nullptr;
m_aSystemData.pShellWidget = GTK_WIDGET(pParent->getWindow());
m_aSystemData.pToolkit = "gtk2";
g_signal_connect( G_OBJECT(m_pSocket), "button-press-event", G_CALLBACK(signalButton), this );
g_signal_connect( G_OBJECT(m_pSocket), "button-release-event", G_CALLBACK(signalButton), this );

View File

@@ -1027,6 +1027,7 @@ void GtkSalFrame::InitCommon()
m_aSystemData.nScreen = m_nXScreen.getXScreen();
m_aSystemData.pAppContext = nullptr;
m_aSystemData.pShellWidget = m_aSystemData.pWidget;
m_aSystemData.pToolkit = "gtk2";
m_bGraphics = false;
m_pGraphics = nullptr;

View File

@@ -1096,6 +1096,7 @@ void GtkSalFrame::InitCommon()
m_aSystemData.nScreen = m_nXScreen.getXScreen();
m_aSystemData.pAppContext = nullptr;
m_aSystemData.pShellWidget = m_aSystemData.pWidget;
m_aSystemData.pToolkit = "gtk3";
m_bGraphics = false;
m_pGraphics = nullptr;

View File

@@ -36,7 +36,7 @@ GtkSalObject::GtkSalObject( GtkSalFrame* pParent, bool bShow )
if( pParent )
{
// our plug window
m_pSocket = gtk_drawing_area_new();
m_pSocket = gtk_grid_new();
Show( bShow );
// insert into container
gtk_fixed_put( pParent->getFixedContainer(),
@@ -45,10 +45,6 @@ GtkSalObject::GtkSalObject( GtkSalFrame* pParent, bool bShow )
// realize so we can get a window id
gtk_widget_realize( m_pSocket );
// make it transparent; some plugins may not insert
// their own window here but use the socket window itself
gtk_widget_set_app_paintable( m_pSocket, TRUE );
// system data
m_aSystemData.nSize = sizeof( SystemEnvData );
m_aSystemData.aWindow = pParent->GetNativeWindowHandle(m_pSocket);
@@ -58,6 +54,7 @@ GtkSalObject::GtkSalObject( GtkSalFrame* pParent, bool bShow )
m_aSystemData.nScreen = pParent->getXScreenNumber().getXScreen();
m_aSystemData.pAppContext = nullptr;
m_aSystemData.pShellWidget = GTK_WIDGET(pParent->getWindow());
m_aSystemData.pToolkit = "gtk3";
g_signal_connect( G_OBJECT(m_pSocket), "button-press-event", G_CALLBACK(signalButton), this );
g_signal_connect( G_OBJECT(m_pSocket), "button-release-event", G_CALLBACK(signalButton), this );