1*f39251c4SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*f39251c4SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*f39251c4SAndrew Rist * or more contributor license agreements. See the NOTICE file 5*f39251c4SAndrew Rist * distributed with this work for additional information 6*f39251c4SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*f39251c4SAndrew Rist * to you under the Apache License, Version 2.0 (the 8*f39251c4SAndrew Rist * "License"); you may not use this file except in compliance 9*f39251c4SAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 11*f39251c4SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 13*f39251c4SAndrew Rist * Unless required by applicable law or agreed to in writing, 14*f39251c4SAndrew Rist * software distributed under the License is distributed on an 15*f39251c4SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*f39251c4SAndrew Rist * KIND, either express or implied. See the License for the 17*f39251c4SAndrew Rist * specific language governing permissions and limitations 18*f39251c4SAndrew Rist * under the License. 19cdf0e10cSrcweir * 20*f39251c4SAndrew Rist *************************************************************/ 21*f39251c4SAndrew Rist 22*f39251c4SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir #include "gstplayer.hxx" 25cdf0e10cSrcweir #include "gstwindow.hxx" 26cdf0e10cSrcweir #include "gstframegrabber.hxx" 27cdf0e10cSrcweir #include <stdio.h> 28cdf0e10cSrcweir #include <unistd.h> 29cdf0e10cSrcweir #include <math.h> 30cdf0e10cSrcweir #include <string> 31cdf0e10cSrcweir #include <gst/gstelement.h> 32cdf0e10cSrcweir #include <gst/interfaces/xoverlay.h> 33cdf0e10cSrcweir 34cdf0e10cSrcweir 35cdf0e10cSrcweir // maximum timeout time in nanoseconds 36cdf0e10cSrcweir #define GST_MAX_TIMEOUT (2500 * GST_MSECOND) 37cdf0e10cSrcweir 38cdf0e10cSrcweir using namespace ::com::sun::star; 39cdf0e10cSrcweir 40cdf0e10cSrcweir namespace avmedia 41cdf0e10cSrcweir { 42cdf0e10cSrcweir namespace gst 43cdf0e10cSrcweir { 44cdf0e10cSrcweir const double NANO_TIME_FACTOR = 1000000000.0; 45cdf0e10cSrcweir 46cdf0e10cSrcweir const long VIDEO_DEFAULT_WIDTH = 256; 47cdf0e10cSrcweir const long VIDEO_DEFAULT_HEIGHT = 192; 48cdf0e10cSrcweir 49cdf0e10cSrcweir // ---------------- 50cdf0e10cSrcweir // - GstBusSource - 51cdf0e10cSrcweir // ---------------- 52cdf0e10cSrcweir 53cdf0e10cSrcweir struct GstBusSource : public GSource 54cdf0e10cSrcweir { 55cdf0e10cSrcweir GstBus* mpBus; 56cdf0e10cSrcweir 57cdf0e10cSrcweir GstBusSource() : 58cdf0e10cSrcweir mpBus( NULL ) 59cdf0e10cSrcweir {} 60cdf0e10cSrcweir 61cdf0e10cSrcweir ~GstBusSource() 62cdf0e10cSrcweir {} 63cdf0e10cSrcweir }; 64cdf0e10cSrcweir 65cdf0e10cSrcweir 66cdf0e10cSrcweir // ----------------------------------------------------------------------- 67cdf0e10cSrcweir extern "C" 68cdf0e10cSrcweir { 69cdf0e10cSrcweir 70cdf0e10cSrcweir static gpointer 71cdf0e10cSrcweir lcl_implThreadFunc( gpointer pData ) 72cdf0e10cSrcweir { 73cdf0e10cSrcweir return( pData ? static_cast< Player* >( pData )->run() : NULL ); 74cdf0e10cSrcweir } 75cdf0e10cSrcweir 76cdf0e10cSrcweir static gboolean 77cdf0e10cSrcweir lcl_implBusCheck( GSource* pSource ) 78cdf0e10cSrcweir { 79cdf0e10cSrcweir GstBusSource* pBusSource = static_cast< GstBusSource* >( pSource ); 80cdf0e10cSrcweir 81cdf0e10cSrcweir return( pBusSource && 82cdf0e10cSrcweir GST_IS_BUS( pBusSource->mpBus ) && 83cdf0e10cSrcweir gst_bus_have_pending( GST_BUS_CAST( pBusSource->mpBus ) ) ); 84cdf0e10cSrcweir } 85cdf0e10cSrcweir 86cdf0e10cSrcweir 87cdf0e10cSrcweir static gboolean 88cdf0e10cSrcweir lcl_implBusPrepare( GSource* pSource, gint* pTimeout ) 89cdf0e10cSrcweir { 90cdf0e10cSrcweir if (pTimeout) 91cdf0e10cSrcweir { 92cdf0e10cSrcweir *pTimeout = 0; 93cdf0e10cSrcweir } 94cdf0e10cSrcweir 95cdf0e10cSrcweir return lcl_implBusCheck(pSource); 96cdf0e10cSrcweir } 97cdf0e10cSrcweir 98cdf0e10cSrcweir static gboolean 99cdf0e10cSrcweir lcl_implBusDispatch( GSource* pSource, 100cdf0e10cSrcweir GSourceFunc /*aCallback*/, 101cdf0e10cSrcweir gpointer pData ) 102cdf0e10cSrcweir { 103cdf0e10cSrcweir GstBusSource* pBusSource = static_cast< GstBusSource* >( pSource ); 104cdf0e10cSrcweir gboolean bRet = false; 105cdf0e10cSrcweir 106cdf0e10cSrcweir if( pData && pBusSource && GST_IS_BUS( pBusSource->mpBus ) ) 107cdf0e10cSrcweir { 108cdf0e10cSrcweir GstMessage* pMsg = gst_bus_pop( pBusSource->mpBus ); 109cdf0e10cSrcweir 110cdf0e10cSrcweir if( pMsg ) 111cdf0e10cSrcweir { 112cdf0e10cSrcweir bRet = static_cast< Player* >( pData )->busCallback( 113cdf0e10cSrcweir pBusSource->mpBus, pMsg ); 114cdf0e10cSrcweir gst_message_unref( pMsg ); 115cdf0e10cSrcweir } 116cdf0e10cSrcweir } 117cdf0e10cSrcweir 118cdf0e10cSrcweir return( bRet ); 119cdf0e10cSrcweir } 120cdf0e10cSrcweir 121cdf0e10cSrcweir static void 122cdf0e10cSrcweir lcl_implBusFinalize( GSource* pSource ) 123cdf0e10cSrcweir { 124cdf0e10cSrcweir GstBusSource* pBusSource = static_cast< GstBusSource* >( pSource ); 125cdf0e10cSrcweir 126cdf0e10cSrcweir if( pBusSource && pBusSource->mpBus ) 127cdf0e10cSrcweir { 128cdf0e10cSrcweir gst_object_unref( pBusSource->mpBus ); 129cdf0e10cSrcweir pBusSource->mpBus = NULL; 130cdf0e10cSrcweir } 131cdf0e10cSrcweir } 132cdf0e10cSrcweir 133cdf0e10cSrcweir static gboolean 134cdf0e10cSrcweir lcl_implIdleFunc( gpointer pData ) 135cdf0e10cSrcweir { 136cdf0e10cSrcweir return( pData ? static_cast< Player* >( pData )->idle() : true ); 137cdf0e10cSrcweir } 138cdf0e10cSrcweir 139cdf0e10cSrcweir static GstBusSyncReply 140cdf0e10cSrcweir lcl_implHandleCreateWindowFunc( GstBus* pBus, GstMessage* pMsg, gpointer pData ) 141cdf0e10cSrcweir { 142cdf0e10cSrcweir return (pData) 143cdf0e10cSrcweir ? static_cast< Player* >( pData )->handleCreateWindow( pBus, pMsg ) 144cdf0e10cSrcweir : GST_BUS_PASS; 145cdf0e10cSrcweir } 146cdf0e10cSrcweir 147cdf0e10cSrcweir } // extern "C" 148cdf0e10cSrcweir 149cdf0e10cSrcweir 150cdf0e10cSrcweir 151cdf0e10cSrcweir // --------------- 152cdf0e10cSrcweir // - Player - 153cdf0e10cSrcweir // --------------- 154cdf0e10cSrcweir Player::Player( GString* pURI ) : 155cdf0e10cSrcweir Player_BASE(m_aMutex), 156cdf0e10cSrcweir mpMutex( g_mutex_new() ), 157cdf0e10cSrcweir mpCond( g_cond_new() ), 158cdf0e10cSrcweir mpThread( NULL ), 159cdf0e10cSrcweir mpContext( NULL ), 160cdf0e10cSrcweir mpLoop( NULL ), 161cdf0e10cSrcweir mpPlayer( NULL ), 162cdf0e10cSrcweir mpURI( pURI ), 163cdf0e10cSrcweir mpPlayerWindow( NULL ), 164cdf0e10cSrcweir mnIsVideoSource( 0 ), 165cdf0e10cSrcweir mnVideoWidth( 0 ), 166cdf0e10cSrcweir mnVideoHeight( 0 ), 167cdf0e10cSrcweir mnInitialized( 0 ), 168cdf0e10cSrcweir mnVolumeDB( 0 ), 169cdf0e10cSrcweir mnLooping( 0 ), 170cdf0e10cSrcweir mnQuit( 0 ), 171cdf0e10cSrcweir mnVideoWindowSet( 0 ), 172cdf0e10cSrcweir mnInitFail( 0 ) 173cdf0e10cSrcweir { 174cdf0e10cSrcweir // initialize GStreamer framework only once 175cdf0e10cSrcweir static bool bGstInitialized = false; 176cdf0e10cSrcweir 177cdf0e10cSrcweir if( !bGstInitialized ) 178cdf0e10cSrcweir { 179cdf0e10cSrcweir gst_init( NULL, NULL ); 180cdf0e10cSrcweir bGstInitialized = true; 181cdf0e10cSrcweir } 182cdf0e10cSrcweir 183cdf0e10cSrcweir if( pURI ) 184cdf0e10cSrcweir { 185cdf0e10cSrcweir OSL_TRACE( ">>> --------------------------------" ); 186cdf0e10cSrcweir OSL_TRACE( ">>> Creating Player object with URL: %s", pURI->str ); 187cdf0e10cSrcweir 188cdf0e10cSrcweir mpThread = g_thread_create( &lcl_implThreadFunc, this, true, NULL ); 189cdf0e10cSrcweir } 190cdf0e10cSrcweir } 191cdf0e10cSrcweir 192cdf0e10cSrcweir // ------------------------------------------------------------------------------ 193cdf0e10cSrcweir 194cdf0e10cSrcweir Player::~Player() 195cdf0e10cSrcweir { 196cdf0e10cSrcweir if( g_atomic_pointer_get( &mpPlayer ) ) 197cdf0e10cSrcweir { 198cdf0e10cSrcweir implQuitThread(); 199cdf0e10cSrcweir } 200cdf0e10cSrcweir 201cdf0e10cSrcweir // cleanup 202cdf0e10cSrcweir g_cond_free( mpCond ); 203cdf0e10cSrcweir g_mutex_free( mpMutex ); 204cdf0e10cSrcweir g_string_free( mpURI, false ); 205cdf0e10cSrcweir } 206cdf0e10cSrcweir 207cdf0e10cSrcweir // ------------------------------------------------------------------------------ 208cdf0e10cSrcweir Player* Player::create( const ::rtl::OUString& rURL ) 209cdf0e10cSrcweir { 210cdf0e10cSrcweir Player* pPlayer = NULL; 211cdf0e10cSrcweir 212cdf0e10cSrcweir if( rURL.getLength() ) 213cdf0e10cSrcweir { 214cdf0e10cSrcweir // safely initialize GLib threading framework 215cdf0e10cSrcweir try 216cdf0e10cSrcweir { 217cdf0e10cSrcweir if( !g_thread_supported() ) 218cdf0e10cSrcweir { 219cdf0e10cSrcweir g_thread_init( NULL ); 220cdf0e10cSrcweir } 221cdf0e10cSrcweir } 222cdf0e10cSrcweir catch( ... ) 223cdf0e10cSrcweir {} 224cdf0e10cSrcweir 225cdf0e10cSrcweir if( g_thread_supported() ) 226cdf0e10cSrcweir { 227cdf0e10cSrcweir const INetURLObject aURL( rURL ); 228cdf0e10cSrcweir 229cdf0e10cSrcweir if( aURL.GetProtocol() != INET_PROT_NOT_VALID ) 230cdf0e10cSrcweir { 231cdf0e10cSrcweir GString* pURI = g_string_new( ::rtl::OUStringToOString( 232cdf0e10cSrcweir aURL.GetMainURL( INetURLObject::NO_DECODE ), 233cdf0e10cSrcweir RTL_TEXTENCODING_UTF8 ).getStr() ); 234cdf0e10cSrcweir 235cdf0e10cSrcweir if( pURI->len ) 236cdf0e10cSrcweir { 237cdf0e10cSrcweir pPlayer = new Player( pURI ); 238cdf0e10cSrcweir 239cdf0e10cSrcweir // wait until thread signals that it has finished initialization 240cdf0e10cSrcweir if( pPlayer->mpThread ) 241cdf0e10cSrcweir { 242cdf0e10cSrcweir g_mutex_lock( pPlayer->mpMutex ); 243cdf0e10cSrcweir 244cdf0e10cSrcweir while( !pPlayer->implIsInitialized() ) 245cdf0e10cSrcweir { 246cdf0e10cSrcweir g_cond_wait( pPlayer->mpCond, pPlayer->mpMutex ); 247cdf0e10cSrcweir } 248cdf0e10cSrcweir 249cdf0e10cSrcweir g_mutex_unlock( pPlayer->mpMutex ); 250cdf0e10cSrcweir } 251cdf0e10cSrcweir 252cdf0e10cSrcweir // check if player pipeline could be initialized 253cdf0e10cSrcweir if( !pPlayer->mpPlayer ) 254cdf0e10cSrcweir { 255cdf0e10cSrcweir delete pPlayer; 256cdf0e10cSrcweir pPlayer = NULL; 257cdf0e10cSrcweir } 258cdf0e10cSrcweir } 259cdf0e10cSrcweir else 260cdf0e10cSrcweir { 261cdf0e10cSrcweir g_string_free( pURI, false ); 262cdf0e10cSrcweir } 263cdf0e10cSrcweir } 264cdf0e10cSrcweir } 265cdf0e10cSrcweir } 266cdf0e10cSrcweir 267cdf0e10cSrcweir return( pPlayer ); 268cdf0e10cSrcweir } 269cdf0e10cSrcweir 270cdf0e10cSrcweir // ------------------------------------------------------------------------------ 271cdf0e10cSrcweir void SAL_CALL Player::start() 272cdf0e10cSrcweir throw( uno::RuntimeException ) 273cdf0e10cSrcweir { 274cdf0e10cSrcweir ::osl::MutexGuard aGuard(m_aMutex); 275cdf0e10cSrcweir if( implInitPlayer() && !isPlaying() ) 276cdf0e10cSrcweir { 277cdf0e10cSrcweir gst_element_set_state( mpPlayer, GST_STATE_PLAYING ); 278cdf0e10cSrcweir } 279cdf0e10cSrcweir } 280cdf0e10cSrcweir 281cdf0e10cSrcweir // ------------------------------------------------------------------------------ 282cdf0e10cSrcweir void SAL_CALL Player::stop() 283cdf0e10cSrcweir throw( uno::RuntimeException ) 284cdf0e10cSrcweir { 285cdf0e10cSrcweir ::osl::MutexGuard aGuard(m_aMutex); 286cdf0e10cSrcweir if( implInitPlayer() && isPlaying() ) 287cdf0e10cSrcweir { 288cdf0e10cSrcweir gst_element_set_state( mpPlayer, GST_STATE_PAUSED ); 289cdf0e10cSrcweir } 290cdf0e10cSrcweir } 291cdf0e10cSrcweir 292cdf0e10cSrcweir // ------------------------------------------------------------------------------ 293cdf0e10cSrcweir sal_Bool SAL_CALL Player::isPlaying() 294cdf0e10cSrcweir throw( uno::RuntimeException ) 295cdf0e10cSrcweir { 296cdf0e10cSrcweir GstState aState = GST_STATE_NULL; 297cdf0e10cSrcweir ::osl::MutexGuard aGuard(m_aMutex); 298cdf0e10cSrcweir if( mpPlayer ) 299cdf0e10cSrcweir { 300cdf0e10cSrcweir gst_element_get_state( mpPlayer, &aState, NULL, GST_MAX_TIMEOUT ); 301cdf0e10cSrcweir } 302cdf0e10cSrcweir 303cdf0e10cSrcweir return( GST_STATE_PLAYING == aState ); 304cdf0e10cSrcweir } 305cdf0e10cSrcweir 306cdf0e10cSrcweir // ------------------------------------------------------------------------------ 307cdf0e10cSrcweir double SAL_CALL Player::getDuration() 308cdf0e10cSrcweir throw( uno::RuntimeException ) 309cdf0e10cSrcweir { 310cdf0e10cSrcweir ::osl::MutexGuard aGuard(m_aMutex); 311cdf0e10cSrcweir gint64 nDuration = 0; 312cdf0e10cSrcweir 313cdf0e10cSrcweir if( implInitPlayer() ) 314cdf0e10cSrcweir { 315cdf0e10cSrcweir GstFormat aFormat = GST_FORMAT_TIME; 316cdf0e10cSrcweir 317cdf0e10cSrcweir if( !gst_element_query_duration( mpPlayer, &aFormat, &nDuration ) || 318cdf0e10cSrcweir ( GST_FORMAT_TIME != aFormat ) || 319cdf0e10cSrcweir ( nDuration < 0 ) ) 320cdf0e10cSrcweir { 321cdf0e10cSrcweir nDuration = 0; 322cdf0e10cSrcweir } 323cdf0e10cSrcweir } 324cdf0e10cSrcweir 325cdf0e10cSrcweir return( static_cast< double >( nDuration ) / NANO_TIME_FACTOR ); 326cdf0e10cSrcweir } 327cdf0e10cSrcweir 328cdf0e10cSrcweir // ------------------------------------------------------------------------------ 329cdf0e10cSrcweir void SAL_CALL Player::setMediaTime( double fTime ) 330cdf0e10cSrcweir throw( uno::RuntimeException ) 331cdf0e10cSrcweir { 332cdf0e10cSrcweir ::osl::MutexGuard aGuard(m_aMutex); 333cdf0e10cSrcweir if( implInitPlayer() ) 334cdf0e10cSrcweir { 335cdf0e10cSrcweir fTime = ::std::min( ::std::max( fTime, 0.0 ), getDuration() ); 336cdf0e10cSrcweir 337cdf0e10cSrcweir gst_element_seek_simple( mpPlayer, GST_FORMAT_TIME, 338cdf0e10cSrcweir (GstSeekFlags) ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT ), 339cdf0e10cSrcweir static_cast< gint64 >( fTime * NANO_TIME_FACTOR ) ); 340cdf0e10cSrcweir } 341cdf0e10cSrcweir } 342cdf0e10cSrcweir 343cdf0e10cSrcweir // ------------------------------------------------------------------------------ 344cdf0e10cSrcweir double SAL_CALL Player::getMediaTime() 345cdf0e10cSrcweir throw( uno::RuntimeException ) 346cdf0e10cSrcweir { 347cdf0e10cSrcweir double fRet = 0.0; 348cdf0e10cSrcweir ::osl::MutexGuard aGuard(m_aMutex); 349cdf0e10cSrcweir if( implInitPlayer() ) 350cdf0e10cSrcweir { 351cdf0e10cSrcweir GstFormat aFormat = GST_FORMAT_TIME; 352cdf0e10cSrcweir gint64 nCurTime = 0; 353cdf0e10cSrcweir 354cdf0e10cSrcweir if( gst_element_query_position( mpPlayer, &aFormat, &nCurTime ) && 355cdf0e10cSrcweir ( GST_FORMAT_TIME == aFormat ) && 356cdf0e10cSrcweir ( nCurTime >= 0 ) ) 357cdf0e10cSrcweir { 358cdf0e10cSrcweir fRet = static_cast< double >( nCurTime ) / NANO_TIME_FACTOR; 359cdf0e10cSrcweir } 360cdf0e10cSrcweir } 361cdf0e10cSrcweir 362cdf0e10cSrcweir return( fRet ); 363cdf0e10cSrcweir } 364cdf0e10cSrcweir 365cdf0e10cSrcweir // ------------------------------------------------------------------------------ 366cdf0e10cSrcweir void SAL_CALL Player::setStopTime( double /* fTime */ ) 367cdf0e10cSrcweir throw( uno::RuntimeException ) 368cdf0e10cSrcweir { 369cdf0e10cSrcweir OSL_TRACE( "GStreamer method avmedia::gst::Player::setStopTime needs to be implemented" ); 370cdf0e10cSrcweir 371cdf0e10cSrcweir /* Currently no need for implementation since higher levels of code don't use this method at all 372cdf0e10cSrcweir !!! TODO: needs to be implemented if this functionality is needed at a later point of time 373cdf0e10cSrcweir if( implInitPlayer() ) 374cdf0e10cSrcweir { 375cdf0e10cSrcweir } 376cdf0e10cSrcweir 377cdf0e10cSrcweir */ 378cdf0e10cSrcweir } 379cdf0e10cSrcweir 380cdf0e10cSrcweir // ------------------------------------------------------------------------------ 381cdf0e10cSrcweir double SAL_CALL Player::getStopTime() 382cdf0e10cSrcweir throw( uno::RuntimeException ) 383cdf0e10cSrcweir { 384cdf0e10cSrcweir /* 385cdf0e10cSrcweir Currently no need for implementation since higher levels of code don't set a stop time ATM 386cdf0e10cSrcweir !!! TODO: needs to be fully implemented if this functionality is needed at a later point of time 387cdf0e10cSrcweir */ 388cdf0e10cSrcweir ::osl::MutexGuard aGuard(m_aMutex); 389cdf0e10cSrcweir return( getDuration() ); 390cdf0e10cSrcweir } 391cdf0e10cSrcweir 392cdf0e10cSrcweir // ------------------------------------------------------------------------------ 393cdf0e10cSrcweir void SAL_CALL Player::setRate( double /* fRate */ ) 394cdf0e10cSrcweir throw( uno::RuntimeException ) 395cdf0e10cSrcweir { 396cdf0e10cSrcweir OSL_TRACE( "GStreamer method avmedia::gst::Player::setRate needs to be implemented" ); 397cdf0e10cSrcweir 398cdf0e10cSrcweir /* Currently no need for implementation since higher levels of code don't use this method at all 399cdf0e10cSrcweir !!! TODO: needs to be implemented if this functionality is needed at a later point of time 400cdf0e10cSrcweir */ 401cdf0e10cSrcweir } 402cdf0e10cSrcweir 403cdf0e10cSrcweir // ------------------------------------------------------------------------------ 404cdf0e10cSrcweir double SAL_CALL Player::getRate() 405cdf0e10cSrcweir throw( uno::RuntimeException ) 406cdf0e10cSrcweir { 407cdf0e10cSrcweir /* 408cdf0e10cSrcweir Currently no need for implementation since higher levels of code don't set a different rate than 1 ATM 409cdf0e10cSrcweir !!! TODO: needs to be fully implemented if this functionality is needed at a later point of time 410cdf0e10cSrcweir */ 411cdf0e10cSrcweir 412cdf0e10cSrcweir return( 1.0 ); 413cdf0e10cSrcweir } 414cdf0e10cSrcweir 415cdf0e10cSrcweir // ------------------------------------------------------------------------------ 416cdf0e10cSrcweir void SAL_CALL Player::setPlaybackLoop( sal_Bool bSet ) 417cdf0e10cSrcweir throw( uno::RuntimeException ) 418cdf0e10cSrcweir { 419cdf0e10cSrcweir ::osl::MutexGuard aGuard(m_aMutex); 420cdf0e10cSrcweir if (bSet) 421cdf0e10cSrcweir { 422cdf0e10cSrcweir g_atomic_int_compare_and_exchange(&mnLooping, 0, 1); 423cdf0e10cSrcweir } 424cdf0e10cSrcweir else 425cdf0e10cSrcweir { 426cdf0e10cSrcweir g_atomic_int_compare_and_exchange(&mnLooping, 1, 0); 427cdf0e10cSrcweir } 428cdf0e10cSrcweir } 429cdf0e10cSrcweir 430cdf0e10cSrcweir // ------------------------------------------------------------------------------ 431cdf0e10cSrcweir sal_Bool SAL_CALL Player::isPlaybackLoop() 432cdf0e10cSrcweir throw( uno::RuntimeException ) 433cdf0e10cSrcweir { 434cdf0e10cSrcweir ::osl::MutexGuard aGuard(m_aMutex); 435cdf0e10cSrcweir return( g_atomic_int_get( &mnLooping ) > 0 ); 436cdf0e10cSrcweir } 437cdf0e10cSrcweir 438cdf0e10cSrcweir // ------------------------------------------------------------------------------ 439cdf0e10cSrcweir void SAL_CALL Player::setMute( sal_Bool bSet ) 440cdf0e10cSrcweir throw( uno::RuntimeException ) 441cdf0e10cSrcweir { 442cdf0e10cSrcweir ::osl::MutexGuard aGuard(m_aMutex); 443cdf0e10cSrcweir if( implInitPlayer() && ( bSet != isMute() ) ) 444cdf0e10cSrcweir { 445cdf0e10cSrcweir if( bSet ) 446cdf0e10cSrcweir { 447cdf0e10cSrcweir g_object_set( mpPlayer, "volume", 0.0, NULL ); 448cdf0e10cSrcweir } 449cdf0e10cSrcweir else 450cdf0e10cSrcweir { 451cdf0e10cSrcweir setVolumeDB( mnVolumeDB ); 452cdf0e10cSrcweir } 453cdf0e10cSrcweir } 454cdf0e10cSrcweir } 455cdf0e10cSrcweir 456cdf0e10cSrcweir // ------------------------------------------------------------------------------ 457cdf0e10cSrcweir sal_Bool SAL_CALL Player::isMute() 458cdf0e10cSrcweir throw( uno::RuntimeException ) 459cdf0e10cSrcweir { 460cdf0e10cSrcweir gdouble fGstVolume = 1.0; 461cdf0e10cSrcweir ::osl::MutexGuard aGuard(m_aMutex); 462cdf0e10cSrcweir 463cdf0e10cSrcweir if( implInitPlayer() ) 464cdf0e10cSrcweir { 465cdf0e10cSrcweir g_object_get( mpPlayer, "volume", &fGstVolume, NULL ); 466cdf0e10cSrcweir } 467cdf0e10cSrcweir 468cdf0e10cSrcweir return( 0.0 == fGstVolume ); 469cdf0e10cSrcweir } 470cdf0e10cSrcweir 471cdf0e10cSrcweir // ------------------------------------------------------------------------------ 472cdf0e10cSrcweir void SAL_CALL Player::setVolumeDB( sal_Int16 nVolumeDB ) 473cdf0e10cSrcweir throw( uno::RuntimeException ) 474cdf0e10cSrcweir { 475cdf0e10cSrcweir ::osl::MutexGuard aGuard(m_aMutex); 476cdf0e10cSrcweir if( implInitPlayer() ) 477cdf0e10cSrcweir { 478cdf0e10cSrcweir g_mutex_lock( mpMutex ); 479cdf0e10cSrcweir mnVolumeDB = nVolumeDB; 480cdf0e10cSrcweir g_mutex_unlock( mpMutex ); 481cdf0e10cSrcweir 482cdf0e10cSrcweir // maximum gain for gstreamer volume is 10 483cdf0e10cSrcweir double fGstVolume = pow( 10.0, static_cast< double >( ::std::min( 484cdf0e10cSrcweir nVolumeDB, static_cast< sal_Int16 >( 20 ) ) / 20.0 ) ); 485cdf0e10cSrcweir 486cdf0e10cSrcweir g_object_set( mpPlayer, "volume", fGstVolume, NULL ); 487cdf0e10cSrcweir } 488cdf0e10cSrcweir } 489cdf0e10cSrcweir 490cdf0e10cSrcweir // ------------------------------------------------------------------------------ 491cdf0e10cSrcweir sal_Int16 SAL_CALL Player::getVolumeDB() 492cdf0e10cSrcweir throw( uno::RuntimeException ) 493cdf0e10cSrcweir { 494cdf0e10cSrcweir ::osl::MutexGuard aGuard(m_aMutex); 495cdf0e10cSrcweir return( static_cast< sal_Int16 >( g_atomic_int_get( &mnVolumeDB ) ) ); 496cdf0e10cSrcweir } 497cdf0e10cSrcweir 498cdf0e10cSrcweir // ------------------------------------------------------------------------------ 499cdf0e10cSrcweir awt::Size SAL_CALL Player::getPreferredPlayerWindowSize() 500cdf0e10cSrcweir throw( uno::RuntimeException ) 501cdf0e10cSrcweir { 502cdf0e10cSrcweir awt::Size aSize( 0, 0 ); 503cdf0e10cSrcweir ::osl::MutexGuard aGuard(m_aMutex); 504cdf0e10cSrcweir 505cdf0e10cSrcweir if( implInitPlayer() && ( g_atomic_int_get( &mnIsVideoSource ) > 0 ) ) 506cdf0e10cSrcweir { 507cdf0e10cSrcweir aSize.Width = g_atomic_int_get( &mnVideoWidth ); 508cdf0e10cSrcweir aSize.Height = g_atomic_int_get( &mnVideoHeight ); 509cdf0e10cSrcweir 510cdf0e10cSrcweir // if we have a video source, but no size is given => use default size 511cdf0e10cSrcweir if( ( aSize.Width <= 0 ) || ( aSize.Height <= 0 ) ) 512cdf0e10cSrcweir { 513cdf0e10cSrcweir aSize.Width = VIDEO_DEFAULT_WIDTH; 514cdf0e10cSrcweir aSize.Height = VIDEO_DEFAULT_HEIGHT; 515cdf0e10cSrcweir } 516cdf0e10cSrcweir } 517cdf0e10cSrcweir 518cdf0e10cSrcweir OSL_TRACE( ">>> Requested preferred video size is: %d x %d pixel", aSize.Width, aSize.Height ); 519cdf0e10cSrcweir 520cdf0e10cSrcweir return( aSize ); 521cdf0e10cSrcweir } 522cdf0e10cSrcweir 523cdf0e10cSrcweir // ------------------------------------------------------------------------------ 524cdf0e10cSrcweir uno::Reference< ::media::XPlayerWindow > SAL_CALL Player::createPlayerWindow( 525cdf0e10cSrcweir const uno::Sequence< uno::Any >& rArguments ) 526cdf0e10cSrcweir throw( uno::RuntimeException ) 527cdf0e10cSrcweir { 528cdf0e10cSrcweir ::osl::MutexGuard aGuard(m_aMutex); 529cdf0e10cSrcweir uno::Reference< ::media::XPlayerWindow > xRet; 530cdf0e10cSrcweir awt::Size aSize( getPreferredPlayerWindowSize() ); 531cdf0e10cSrcweir 532cdf0e10cSrcweir OSL_ENSURE( !g_atomic_pointer_get( &mpPlayerWindow ), "::avmedia::gst::Player already has a player window" ); 533cdf0e10cSrcweir 534cdf0e10cSrcweir if( ( aSize.Width > 0 ) && ( aSize.Height > 0 ) ) 535cdf0e10cSrcweir { 536cdf0e10cSrcweir Window* pPlayerWindow = new Window( *this ); 537cdf0e10cSrcweir 538cdf0e10cSrcweir xRet = pPlayerWindow; 539cdf0e10cSrcweir 540cdf0e10cSrcweir if( !pPlayerWindow->create( rArguments ) ) 541cdf0e10cSrcweir { 542cdf0e10cSrcweir xRet.clear(); 543cdf0e10cSrcweir } 544cdf0e10cSrcweir else 545cdf0e10cSrcweir { 546cdf0e10cSrcweir // try to use gconf user configurable video sink first 547cdf0e10cSrcweir GstElement* pVideoSink = gst_element_factory_make( "gconfvideosink", NULL ); 548cdf0e10cSrcweir 549cdf0e10cSrcweir if( ( NULL != pVideoSink ) || 550cdf0e10cSrcweir ( NULL != ( pVideoSink = gst_element_factory_make( "autovideosink", NULL ) ) ) || 551cdf0e10cSrcweir ( NULL != ( pVideoSink = gst_element_factory_make( "xvimagesink", NULL ) ) ) || 552cdf0e10cSrcweir ( NULL != ( pVideoSink = gst_element_factory_make( "ximagesink", NULL ) ) ) ) 553cdf0e10cSrcweir { 554cdf0e10cSrcweir GstState aOldState = GST_STATE_NULL; 555cdf0e10cSrcweir 556cdf0e10cSrcweir mpPlayerWindow = pPlayerWindow; 557cdf0e10cSrcweir gst_element_get_state( mpPlayer, &aOldState, NULL, GST_MAX_TIMEOUT ); 558cdf0e10cSrcweir gst_element_set_state( mpPlayer, GST_STATE_READY ); 559cdf0e10cSrcweir g_object_set( mpPlayer, "video-sink", pVideoSink, NULL ); 560cdf0e10cSrcweir gst_element_set_state( mpPlayer, aOldState ); 561cdf0e10cSrcweir } 562cdf0e10cSrcweir } 563cdf0e10cSrcweir } 564cdf0e10cSrcweir 565cdf0e10cSrcweir return( xRet ); 566cdf0e10cSrcweir } 567cdf0e10cSrcweir 568cdf0e10cSrcweir // ------------------------------------------------------------------------------ 569cdf0e10cSrcweir uno::Reference< media::XFrameGrabber > SAL_CALL Player::createFrameGrabber() 570cdf0e10cSrcweir throw( ::com::sun::star::uno::RuntimeException ) 571cdf0e10cSrcweir { 572cdf0e10cSrcweir ::osl::MutexGuard aGuard(m_aMutex); 573cdf0e10cSrcweir FrameGrabber* pFrameGrabber = NULL; 574cdf0e10cSrcweir const awt::Size aPrefSize( getPreferredPlayerWindowSize() ); 575cdf0e10cSrcweir 576cdf0e10cSrcweir if( ( aPrefSize.Width > 0 ) && ( aPrefSize.Height > 0 ) ) 577cdf0e10cSrcweir { 578cdf0e10cSrcweir pFrameGrabber = FrameGrabber::create( mpURI ); 579cdf0e10cSrcweir } 580cdf0e10cSrcweir 581cdf0e10cSrcweir return( pFrameGrabber ); 582cdf0e10cSrcweir } 583cdf0e10cSrcweir 584cdf0e10cSrcweir // ------------------------------------------------------------------------------ 585cdf0e10cSrcweir void SAL_CALL Player::disposing() 586cdf0e10cSrcweir { 587cdf0e10cSrcweir ::osl::MutexGuard aGuard(m_aMutex); 588cdf0e10cSrcweir if( mpPlayer ) 589cdf0e10cSrcweir { 590cdf0e10cSrcweir stop(); 591cdf0e10cSrcweir implQuitThread(); 592cdf0e10cSrcweir } 593cdf0e10cSrcweir 594cdf0e10cSrcweir OSL_ASSERT( NULL == mpPlayer ); 595cdf0e10cSrcweir } 596cdf0e10cSrcweir 597cdf0e10cSrcweir // ------------------------------------------------------------------------------ 598cdf0e10cSrcweir ::rtl::OUString SAL_CALL Player::getImplementationName() 599cdf0e10cSrcweir throw( uno::RuntimeException ) 600cdf0e10cSrcweir { 601cdf0e10cSrcweir return( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( AVMEDIA_GSTREAMER_PLAYER_IMPLEMENTATIONNAME ) ) ); 602cdf0e10cSrcweir } 603cdf0e10cSrcweir 604cdf0e10cSrcweir // ------------------------------------------------------------------------------ 605cdf0e10cSrcweir sal_Bool SAL_CALL Player::supportsService( const ::rtl::OUString& ServiceName ) 606cdf0e10cSrcweir throw( uno::RuntimeException ) 607cdf0e10cSrcweir { 608cdf0e10cSrcweir return( ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( AVMEDIA_GSTREAMER_PLAYER_SERVICENAME ) ) ); 609cdf0e10cSrcweir } 610cdf0e10cSrcweir 611cdf0e10cSrcweir // ------------------------------------------------------------------------------ 612cdf0e10cSrcweir uno::Sequence< ::rtl::OUString > SAL_CALL Player::getSupportedServiceNames() 613cdf0e10cSrcweir throw( uno::RuntimeException ) 614cdf0e10cSrcweir { 615cdf0e10cSrcweir uno::Sequence< ::rtl::OUString > aRet( 1 ); 616cdf0e10cSrcweir aRet[ 0 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( AVMEDIA_GSTREAMER_PLAYER_SERVICENAME ) ); 617cdf0e10cSrcweir 618cdf0e10cSrcweir return( aRet ); 619cdf0e10cSrcweir } 620cdf0e10cSrcweir 621cdf0e10cSrcweir // ------------------------------------------------------------------------------ 622cdf0e10cSrcweir void Player::implQuitThread() 623cdf0e10cSrcweir { 624cdf0e10cSrcweir if( mpThread ) 625cdf0e10cSrcweir { 626cdf0e10cSrcweir // set quit flag to 1 so that the main loop will be quit in idle 627cdf0e10cSrcweir // handler the next time it is called from the thread's main loop 628cdf0e10cSrcweir g_atomic_int_inc( &mnQuit ); 629cdf0e10cSrcweir 630cdf0e10cSrcweir // wait until loop and as such the thread has quit 631cdf0e10cSrcweir g_thread_join( mpThread ); 632cdf0e10cSrcweir mpThread = NULL; 633cdf0e10cSrcweir } 634cdf0e10cSrcweir } 635cdf0e10cSrcweir 636cdf0e10cSrcweir // ------------------------------------------------------------------------------ 637cdf0e10cSrcweir bool Player::implInitPlayer() 638cdf0e10cSrcweir { 639cdf0e10cSrcweir bool bRet = false; 640cdf0e10cSrcweir 641cdf0e10cSrcweir if( mpPlayer && (mnInitFail < 3) ) 642cdf0e10cSrcweir { 643cdf0e10cSrcweir GstState aState = GST_STATE_NULL; 644cdf0e10cSrcweir 645cdf0e10cSrcweir if( gst_element_get_state( mpPlayer, &aState, NULL, GST_MAX_TIMEOUT ) == GST_STATE_CHANGE_SUCCESS ) 646cdf0e10cSrcweir { 647cdf0e10cSrcweir bRet = ( GST_STATE_PAUSED == aState ) || ( GST_STATE_PLAYING == aState ); 648cdf0e10cSrcweir 649cdf0e10cSrcweir if( !bRet ) 650cdf0e10cSrcweir { 651cdf0e10cSrcweir gst_element_set_state( mpPlayer, GST_STATE_PAUSED ); 652cdf0e10cSrcweir bRet = ( gst_element_get_state( mpPlayer, &aState, NULL, 653cdf0e10cSrcweir GST_MAX_TIMEOUT ) == GST_STATE_CHANGE_SUCCESS ) && 654cdf0e10cSrcweir ( GST_STATE_PAUSED == aState ); 655cdf0e10cSrcweir } 656cdf0e10cSrcweir } 657cdf0e10cSrcweir 658cdf0e10cSrcweir if( ! bRet ) 659cdf0e10cSrcweir mnInitFail++; 660cdf0e10cSrcweir } 661cdf0e10cSrcweir 662cdf0e10cSrcweir return( bRet ); 663cdf0e10cSrcweir } 664cdf0e10cSrcweir 665cdf0e10cSrcweir // ------------------------------------------------------------------------------ 666cdf0e10cSrcweir gboolean Player::busCallback( GstBus* /*pBus*/, 667cdf0e10cSrcweir GstMessage* pMsg ) 668cdf0e10cSrcweir { 669cdf0e10cSrcweir if( pMsg && mpLoop ) 670cdf0e10cSrcweir { 671cdf0e10cSrcweir switch( GST_MESSAGE_TYPE( pMsg ) ) 672cdf0e10cSrcweir { 673cdf0e10cSrcweir case ( GST_MESSAGE_EOS ): 674cdf0e10cSrcweir { 675cdf0e10cSrcweir if( g_atomic_int_get( &mnLooping ) > 0 ) 676cdf0e10cSrcweir { 677cdf0e10cSrcweir setMediaTime( 0.0 ); 678cdf0e10cSrcweir start(); 679cdf0e10cSrcweir } 680cdf0e10cSrcweir else 681cdf0e10cSrcweir { 682cdf0e10cSrcweir stop(); 683cdf0e10cSrcweir } 684cdf0e10cSrcweir } 685cdf0e10cSrcweir break; 686cdf0e10cSrcweir 687cdf0e10cSrcweir case ( GST_MESSAGE_ERROR ): 688cdf0e10cSrcweir { 689cdf0e10cSrcweir gchar* pDebug; 690cdf0e10cSrcweir GError* pErr; 691cdf0e10cSrcweir 692cdf0e10cSrcweir gst_message_parse_error( pMsg, &pErr, &pDebug ); 693cdf0e10cSrcweir fprintf( stderr, "Error: %s\n", pErr->message ); 694cdf0e10cSrcweir 695cdf0e10cSrcweir g_free( pDebug ); 696cdf0e10cSrcweir g_error_free( pErr ); 697cdf0e10cSrcweir } 698cdf0e10cSrcweir break; 699cdf0e10cSrcweir 700cdf0e10cSrcweir default: 701cdf0e10cSrcweir { 702cdf0e10cSrcweir break; 703cdf0e10cSrcweir } 704cdf0e10cSrcweir } 705cdf0e10cSrcweir } 706cdf0e10cSrcweir 707cdf0e10cSrcweir return( true ); 708cdf0e10cSrcweir } 709cdf0e10cSrcweir 710cdf0e10cSrcweir // ------------------------------------------------------------------------------ 711cdf0e10cSrcweir void Player::implHandleNewElementFunc( GstBin* /* pBin */, 712cdf0e10cSrcweir GstElement* pElement, 713cdf0e10cSrcweir gpointer pData ) 714cdf0e10cSrcweir { 715cdf0e10cSrcweir if( pElement ) 716cdf0e10cSrcweir { 717cdf0e10cSrcweir #ifdef DEBUG 718cdf0e10cSrcweir gchar* pElementName = gst_element_get_name( pElement ); 719cdf0e10cSrcweir 720cdf0e10cSrcweir if( pElementName ) 721cdf0e10cSrcweir { 722cdf0e10cSrcweir OSL_TRACE( ">>> Bin has element: %s", pElementName ); 723cdf0e10cSrcweir g_free( pElementName ); 724cdf0e10cSrcweir } 725cdf0e10cSrcweir #endif 726cdf0e10cSrcweir 727cdf0e10cSrcweir if( GST_IS_BIN( pElement ) ) 728cdf0e10cSrcweir { 729cdf0e10cSrcweir // set this handler in case we have a GstBin element 730cdf0e10cSrcweir g_signal_connect( GST_BIN( pElement ), "element-added", 731cdf0e10cSrcweir G_CALLBACK( Player::implHandleNewElementFunc ), pData ); 732cdf0e10cSrcweir } 733cdf0e10cSrcweir 734cdf0e10cSrcweir // watch for all pads that are going to be added to this element; 735cdf0e10cSrcweir g_signal_connect( pElement, "pad-added", 736cdf0e10cSrcweir G_CALLBACK( Player::implHandleNewPadFunc ), pData ); 737cdf0e10cSrcweir } 738cdf0e10cSrcweir } 739cdf0e10cSrcweir 740cdf0e10cSrcweir // ------------------------------------------------------------------------------ 741cdf0e10cSrcweir void Player::implHandleNewPadFunc( GstElement* pElement, 742cdf0e10cSrcweir GstPad* pPad, 743cdf0e10cSrcweir gpointer pData ) 744cdf0e10cSrcweir { 745cdf0e10cSrcweir Player* pPlayer = static_cast< Player* >( pData ); 746cdf0e10cSrcweir 747cdf0e10cSrcweir if( pPlayer && pElement && pPad ) 748cdf0e10cSrcweir { 749cdf0e10cSrcweir #ifdef DEBUG 750cdf0e10cSrcweir gchar* pElementName = gst_element_get_name( pElement ); 751cdf0e10cSrcweir gchar* pPadName = gst_pad_get_name( pPad ); 752cdf0e10cSrcweir 753cdf0e10cSrcweir OSL_TRACE( ">>> Element %s has pad: %s", pElementName, pPadName ); 754cdf0e10cSrcweir 755cdf0e10cSrcweir g_free( pPadName ); 756cdf0e10cSrcweir g_free( pElementName ); 757cdf0e10cSrcweir #endif 758cdf0e10cSrcweir 759cdf0e10cSrcweir GstCaps* pCaps = gst_pad_get_caps( pPad ); 760cdf0e10cSrcweir 761cdf0e10cSrcweir // we are interested only in getting video properties 762cdf0e10cSrcweir // width and height or if we have a video source at all 763cdf0e10cSrcweir if( pCaps ) 764cdf0e10cSrcweir { 765cdf0e10cSrcweir for( gint i = 0, nSize = gst_caps_get_size( pCaps ); i < nSize; ++i ) 766cdf0e10cSrcweir { 767cdf0e10cSrcweir const GstStructure* pStruct = gst_caps_get_structure( pCaps, i ); 768cdf0e10cSrcweir 769cdf0e10cSrcweir if( pStruct ) 770cdf0e10cSrcweir { 771cdf0e10cSrcweir const gchar* pStructName = gst_structure_get_name( pStruct ); 772cdf0e10cSrcweir 773cdf0e10cSrcweir #ifdef DEBUG 774cdf0e10cSrcweir OSL_TRACE( "\t>>> Pad has structure: %s", pStructName ); 775cdf0e10cSrcweir 776cdf0e10cSrcweir for( gint n = 0, nFields = gst_structure_n_fields( pStruct ); n < nFields; ++n ) 777cdf0e10cSrcweir { 778cdf0e10cSrcweir OSL_TRACE( "\t\t>>> Structure has field: %s", gst_structure_nth_field_name( pStruct, n ) ); 779cdf0e10cSrcweir } 780cdf0e10cSrcweir #endif 781cdf0e10cSrcweir 782cdf0e10cSrcweir // just look for structures having 'video' in their names 783cdf0e10cSrcweir if( ::std::string( pStructName ).find( "video" ) != ::std::string::npos ) 784cdf0e10cSrcweir { 785cdf0e10cSrcweir g_atomic_int_inc( &pPlayer->mnIsVideoSource ); 786cdf0e10cSrcweir 787cdf0e10cSrcweir for( gint n = 0, nFields = gst_structure_n_fields( pStruct ); n < nFields; ++n ) 788cdf0e10cSrcweir { 789cdf0e10cSrcweir const gchar* pFieldName = gst_structure_nth_field_name( pStruct, n ); 790cdf0e10cSrcweir gint nValue; 791cdf0e10cSrcweir 792cdf0e10cSrcweir if( ( ::std::string( pFieldName ).find( "width" ) != ::std::string::npos ) && 793cdf0e10cSrcweir gst_structure_get_int( pStruct, pFieldName, &nValue ) ) 794cdf0e10cSrcweir { 795cdf0e10cSrcweir const gint nDiff = nValue - g_atomic_int_get( &pPlayer->mnVideoWidth ); 796cdf0e10cSrcweir g_atomic_int_add( &pPlayer->mnVideoWidth, ::std::max( nDiff, 0 ) ); 797cdf0e10cSrcweir } 798cdf0e10cSrcweir else if( ( ::std::string( pFieldName ).find( "height" ) != ::std::string::npos ) && 799cdf0e10cSrcweir gst_structure_get_int( pStruct, pFieldName, &nValue ) ) 800cdf0e10cSrcweir { 801cdf0e10cSrcweir const gint nDiff = nValue - g_atomic_int_get( &pPlayer->mnVideoHeight ); 802cdf0e10cSrcweir g_atomic_int_add( &pPlayer->mnVideoHeight, ::std::max( nDiff, 0 ) ); 803cdf0e10cSrcweir } 804cdf0e10cSrcweir } 805cdf0e10cSrcweir } 806cdf0e10cSrcweir } 807cdf0e10cSrcweir } 808cdf0e10cSrcweir 809cdf0e10cSrcweir gst_caps_unref( pCaps ); 810cdf0e10cSrcweir } 811cdf0e10cSrcweir } 812cdf0e10cSrcweir } 813cdf0e10cSrcweir 814cdf0e10cSrcweir // ------------------------------------------------------------------------------ 815cdf0e10cSrcweir gboolean Player::idle() 816cdf0e10cSrcweir { 817cdf0e10cSrcweir // test if main loop should quit by comparing with 1 818cdf0e10cSrcweir // and set flag mnQuit to 0 so we call g_main_loop_quit exactly once 819cdf0e10cSrcweir bool const bQuit = g_atomic_int_compare_and_exchange( &mnQuit, 1, 0 ); 820cdf0e10cSrcweir 821cdf0e10cSrcweir if( bQuit ) 822cdf0e10cSrcweir { 823cdf0e10cSrcweir g_main_loop_quit( mpLoop ); 824cdf0e10cSrcweir } 825cdf0e10cSrcweir 826cdf0e10cSrcweir // don't eat up all cpu time 827cdf0e10cSrcweir usleep( 1000 ); 828cdf0e10cSrcweir 829cdf0e10cSrcweir return( true ); 830cdf0e10cSrcweir } 831cdf0e10cSrcweir 832cdf0e10cSrcweir // ------------------------------------------------------------------------------ 833cdf0e10cSrcweir gpointer Player::run() 834cdf0e10cSrcweir { 835cdf0e10cSrcweir static GSourceFuncs aSourceFuncs = 836cdf0e10cSrcweir { 837cdf0e10cSrcweir &lcl_implBusPrepare, 838cdf0e10cSrcweir &lcl_implBusCheck, 839cdf0e10cSrcweir &lcl_implBusDispatch, 840cdf0e10cSrcweir &lcl_implBusFinalize, 841cdf0e10cSrcweir NULL, 842cdf0e10cSrcweir NULL 843cdf0e10cSrcweir }; 844cdf0e10cSrcweir 845cdf0e10cSrcweir if( NULL != ( mpPlayer = gst_element_factory_make( "playbin", NULL ) ) ) 846cdf0e10cSrcweir { 847cdf0e10cSrcweir // initialization 848cdf0e10cSrcweir // no mutex necessary since initialization 849cdf0e10cSrcweir // is synchronous until loop is started 850cdf0e10cSrcweir mpContext = g_main_context_new(); 851cdf0e10cSrcweir mpLoop = g_main_loop_new( mpContext, false ); 852cdf0e10cSrcweir 853cdf0e10cSrcweir // add idle callback 854cdf0e10cSrcweir GSource* pIdleSource = g_idle_source_new(); 855cdf0e10cSrcweir g_source_set_callback( pIdleSource, &lcl_implIdleFunc, this, NULL ); 856cdf0e10cSrcweir g_source_attach( pIdleSource, mpContext ); 857cdf0e10cSrcweir 858cdf0e10cSrcweir // add bus callback 859cdf0e10cSrcweir GSource* pBusSource = g_source_new( &aSourceFuncs, sizeof( GstBusSource ) ); 860cdf0e10cSrcweir static_cast< GstBusSource* >( pBusSource )->mpBus = gst_pipeline_get_bus( GST_PIPELINE( mpPlayer ) ); 861cdf0e10cSrcweir g_source_set_callback( pBusSource, NULL, this, NULL ); 862cdf0e10cSrcweir g_source_attach( pBusSource, mpContext ); 863cdf0e10cSrcweir 864cdf0e10cSrcweir // add bus sync handler to intercept video window creation for setting our own window 865cdf0e10cSrcweir gst_bus_set_sync_handler( static_cast< GstBusSource* >( pBusSource )->mpBus, 866cdf0e10cSrcweir &lcl_implHandleCreateWindowFunc, this ); 867cdf0e10cSrcweir 868cdf0e10cSrcweir // watch for all elements (and pads) that will be added to the playbin, 869cdf0e10cSrcweir // in order to retrieve properties like video width and height 870cdf0e10cSrcweir g_signal_connect( GST_BIN( mpPlayer ), "element-added", 871cdf0e10cSrcweir G_CALLBACK( Player::implHandleNewElementFunc ), this ); 872cdf0e10cSrcweir 873cdf0e10cSrcweir // set source URI for player 874cdf0e10cSrcweir g_object_set( mpPlayer, "uri", mpURI->str, NULL ); 875cdf0e10cSrcweir 876cdf0e10cSrcweir // set video fake sink first, since we only create a player without window here 877cdf0e10cSrcweir // and don't want to have the gstreamer default window appearing 878cdf0e10cSrcweir g_object_set( mpPlayer, "video-sink", gst_element_factory_make( "fakesink", NULL ), NULL ); 879cdf0e10cSrcweir 880cdf0e10cSrcweir // set state of player to READY or destroy object in case of FAILURE 881cdf0e10cSrcweir if( gst_element_set_state( mpPlayer, GST_STATE_READY ) == GST_STATE_CHANGE_FAILURE ) 882cdf0e10cSrcweir { 883cdf0e10cSrcweir gst_object_unref( mpPlayer ); 884cdf0e10cSrcweir mpPlayer = NULL; 885cdf0e10cSrcweir } 886cdf0e10cSrcweir 887cdf0e10cSrcweir g_atomic_int_add( &mnInitialized, 1 ); 888cdf0e10cSrcweir g_cond_signal( mpCond ); 889cdf0e10cSrcweir 890cdf0e10cSrcweir // run the main loop 891cdf0e10cSrcweir g_main_loop_run( mpLoop ); 892cdf0e10cSrcweir 893cdf0e10cSrcweir // clenanup 894cdf0e10cSrcweir // no mutex necessary since other thread joined us (this thread) 895cdf0e10cSrcweir // after setting the quit flag 896cdf0e10cSrcweir if( mpPlayer ) 897cdf0e10cSrcweir { 898cdf0e10cSrcweir gst_element_set_state( mpPlayer, GST_STATE_NULL ); 899cdf0e10cSrcweir gst_object_unref( mpPlayer ); 900cdf0e10cSrcweir mpPlayer = NULL; 901cdf0e10cSrcweir } 902cdf0e10cSrcweir 903cdf0e10cSrcweir g_main_loop_unref( mpLoop ); 904cdf0e10cSrcweir mpLoop = NULL; 905cdf0e10cSrcweir 906cdf0e10cSrcweir g_source_destroy( pBusSource ); 907cdf0e10cSrcweir g_source_unref( pBusSource ); 908cdf0e10cSrcweir 909cdf0e10cSrcweir g_source_destroy( pIdleSource ); 910cdf0e10cSrcweir g_source_unref( pIdleSource ); 911cdf0e10cSrcweir 912cdf0e10cSrcweir g_main_context_unref( mpContext ); 913cdf0e10cSrcweir mpContext = NULL; 914cdf0e10cSrcweir } 915cdf0e10cSrcweir else 916cdf0e10cSrcweir { 917cdf0e10cSrcweir g_atomic_int_add( &mnInitialized, 1 ); 918cdf0e10cSrcweir g_cond_signal( mpCond ); 919cdf0e10cSrcweir } 920cdf0e10cSrcweir 921cdf0e10cSrcweir return( NULL ); 922cdf0e10cSrcweir } 923cdf0e10cSrcweir 924cdf0e10cSrcweir // ------------------------------------------------------------------------------ 925cdf0e10cSrcweir GstBusSyncReply Player::handleCreateWindow( GstBus* /* pBus */, 926cdf0e10cSrcweir GstMessage* pMsg ) 927cdf0e10cSrcweir { 928cdf0e10cSrcweir GstBusSyncReply eRet = GST_BUS_PASS; 929cdf0e10cSrcweir 930cdf0e10cSrcweir if( pMsg && 931cdf0e10cSrcweir ( GST_MESSAGE_TYPE( pMsg ) == GST_MESSAGE_ELEMENT ) && 932cdf0e10cSrcweir gst_structure_has_name( pMsg->structure, "prepare-xwindow-id" ) && 933cdf0e10cSrcweir g_atomic_pointer_get( &mpPlayerWindow ) ) 934cdf0e10cSrcweir { 935cdf0e10cSrcweir OSL_TRACE( ">>> Got Request to create XOverlay" ); 936cdf0e10cSrcweir 937cdf0e10cSrcweir gst_x_overlay_set_xwindow_id( GST_X_OVERLAY( GST_MESSAGE_SRC( pMsg ) ), 938cdf0e10cSrcweir static_cast< Window* >( g_atomic_pointer_get( 939cdf0e10cSrcweir &mpPlayerWindow ) )->getXWindowHandle() ); 940cdf0e10cSrcweir 941cdf0e10cSrcweir gst_message_unref( pMsg ); 942cdf0e10cSrcweir eRet = GST_BUS_DROP; 943cdf0e10cSrcweir } 944cdf0e10cSrcweir 945cdf0e10cSrcweir return( eRet ); 946cdf0e10cSrcweir } 947cdf0e10cSrcweir } // namespace gst 948cdf0e10cSrcweir } // namespace avmedia 949