diff options
author | Michael Meeks <michael.meeks@suse.com> | 2012-09-24 21:54:36 +0100 |
---|---|---|
committer | Michael Meeks <michael.meeks@suse.com> | 2012-09-25 19:14:25 +0100 |
commit | fc6351f5d36f8b6be5e52a2ea1f191de81eacc71 (patch) | |
tree | 90f6b2ba952a9c50bdb54a9420761d83a8696e9e /avmedia | |
parent | 3e46a434eb50f8d73f64be8619598dae6dc32a06 (diff) |
avmedia: first cut at gstreamer frame grabber.
with thanks to Tim-Philipp Müller and Wim Taymans.
Change-Id: Ia095d06ea3cbed85570cc33038f98da0362c1e62
Diffstat (limited to 'avmedia')
-rw-r--r-- | avmedia/Library_avmediagst.mk | 1 | ||||
-rw-r--r-- | avmedia/source/gstreamer/gst_0_10.cxx | 1 | ||||
-rw-r--r-- | avmedia/source/gstreamer/gstframegrabber.cxx | 287 | ||||
-rw-r--r-- | avmedia/source/gstreamer/gstframegrabber.hxx | 35 | ||||
-rw-r--r-- | avmedia/source/gstreamer/gstplayer.cxx | 102 | ||||
-rw-r--r-- | avmedia/source/gstreamer/gstplayer.hxx | 19 |
6 files changed, 256 insertions, 189 deletions
diff --git a/avmedia/Library_avmediagst.mk b/avmedia/Library_avmediagst.mk index ee8a09aadb98..528960bfa1b1 100644 --- a/avmedia/Library_avmediagst.mk +++ b/avmedia/Library_avmediagst.mk @@ -60,6 +60,7 @@ $(eval $(call gb_Library_add_exception_objects,avmediagst,\ avmedia/source/gstreamer/gstplayer \ avmedia/source/gstreamer/gstuno \ avmedia/source/gstreamer/gstwindow \ + avmedia/source/gstreamer/gstframegrabber \ )) # vim: set noet sw=4 ts=4: diff --git a/avmedia/source/gstreamer/gst_0_10.cxx b/avmedia/source/gstreamer/gst_0_10.cxx index c24ec4e5d84f..9f2715b5d9e6 100644 --- a/avmedia/source/gstreamer/gst_0_10.cxx +++ b/avmedia/source/gstreamer/gst_0_10.cxx @@ -21,3 +21,4 @@ #include "gstplayer.cxx" #include "gstuno.cxx" #include "gstwindow.cxx" +#include "gstframegrabber.cxx" diff --git a/avmedia/source/gstreamer/gstframegrabber.cxx b/avmedia/source/gstreamer/gstframegrabber.cxx index a8c09773e24d..c4046f11a1af 100644 --- a/avmedia/source/gstreamer/gstframegrabber.cxx +++ b/avmedia/source/gstreamer/gstframegrabber.cxx @@ -17,206 +17,207 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#include <objbase.h> -#include <strmif.h> -#include <Amvideo.h> -#include <Qedit.h> -#include <uuids.h> +#include "gstframegrabber.hxx" +#include "gstplayer.hxx" -#include "framegrabber.hxx" -#include "player.hxx" +#include <gst/gstbuffer.h> +#include <gst/video/video.h> +#include <gst/video/gstvideosink.h> -#include <tools/stream.hxx> #include <vcl/graph.hxx> -#include <unotools/localfilehelper.hxx> +#include <vcl/bmpacc.hxx> -#define AVMEDIA_GST_FRAMEGRABBER_IMPLEMENTATIONNAME "com.sun.star.comp.avmedia.FrameGrabber_GStreamer" -#define AVMEDIA_GST_FRAMEGRABBER_SERVICENAME "com.sun.star.media.FrameGrabber_GStreamer" +#include <string> + +#ifdef AVMEDIA_GST_0_10 +# define AVMEDIA_GST_FRAMEGRABBER_IMPLEMENTATIONNAME "com.sun.star.comp.avmedia.FrameGrabber_GStreamer_0_10" +# define AVMEDIA_GST_FRAMEGRABBER_SERVICENAME "com.sun.star.media.FrameGrabber_GStreamer_0_10" +#else +# define AVMEDIA_GST_FRAMEGRABBER_IMPLEMENTATIONNAME "com.sun.star.comp.avmedia.FrameGrabber_GStreamer" +# define AVMEDIA_GST_FRAMEGRABBER_SERVICENAME "com.sun.star.media.FrameGrabber_GStreamer" +#endif using namespace ::com::sun::star; namespace avmedia { namespace gstreamer { -// ---------------- -// - FrameGrabber - -// ---------------- - -FrameGrabber::FrameGrabber( const uno::Reference< lang::XMultiServiceFactory >& rxMgr ) : - mxMgr( rxMgr ) -{ - ::CoInitialize( NULL ); -} - -// ------------------------------------------------------------------------------ - -FrameGrabber::~FrameGrabber() +void FrameGrabber::disposePipeline() { - ::CoUninitialize(); + if( mpPipeline != NULL ) + { + gst_element_set_state( mpPipeline, GST_STATE_NULL ); + g_object_unref( G_OBJECT( mpPipeline ) ); + mpPipeline = NULL; + } } -// ------------------------------------------------------------------------------ - -IMediaDet* FrameGrabber::implCreateMediaDet( const OUString& rURL ) const +FrameGrabber::FrameGrabber( const rtl::OUString &rURL ) : + FrameGrabber_BASE() { - IMediaDet* pDet = NULL; - - if( SUCCEEDED( CoCreateInstance( CLSID_MediaDet, NULL, CLSCTX_INPROC_SERVER, IID_IMediaDet, (void**) &pDet ) ) ) - { - String aLocalStr; + gchar *pPipelineStr; + pPipelineStr = g_strdup_printf( +#ifdef AVMEDIA_GST_0_10 + "uridecodebin uri=%s ! ffmpegcolorspace ! videoscale ! appsink " + "name=sink caps=\"video/x-raw-rgb,format=RGB,pixel-aspect-ratio=1/1," + "bpp=(int)24,depth=(int)24,endianness=(int)4321," + "red_mask=(int)0xff0000, green_mask=(int)0x00ff00, blue_mask=(int)0x0000ff\"", +#else + "uridecodebin uri=%s ! videoconvert ! videoscale ! appsink " + "name=sink caps=\"video/x-raw,format=RGB,pixel-aspect-ratio=1/1\"", +#endif + rtl::OUStringToOString( rURL, RTL_TEXTENCODING_UTF8 ).getStr() ); + + GError *pError = NULL; + mpPipeline = gst_parse_launch( pPipelineStr, &pError ); + if( pError != NULL) { + g_warning( "Failed to construct frame-grabber pipeline '%s'\n", pError->message ); + g_error_free( pError ); + disposePipeline(); + } - if( ::utl::LocalFileHelper::ConvertURLToPhysicalName( rURL, aLocalStr ) && aLocalStr.Len() ) - { - if( !SUCCEEDED( pDet->put_Filename( ::SysAllocString( aLocalStr.GetBuffer() ) ) ) ) - { - pDet->Release(); - pDet = NULL; - } + if( mpPipeline ) { + // pre-roll + switch( gst_element_set_state( mpPipeline, GST_STATE_PAUSED ) ) { + case GST_STATE_CHANGE_FAILURE: + case GST_STATE_CHANGE_NO_PREROLL: + g_warning( "failure pre-rolling media" ); + disposePipeline(); + break; + default: + break; } } - - return pDet; + if( mpPipeline && + gst_element_get_state( mpPipeline, NULL, NULL, 5 * GST_SECOND ) == GST_STATE_CHANGE_FAILURE ) + disposePipeline(); } -// ------------------------------------------------------------------------------ - -bool FrameGrabber::create( const OUString& rURL ) +FrameGrabber::~FrameGrabber() { - // just check if a MediaDet interface can be created with the given URL - IMediaDet* pDet = implCreateMediaDet( rURL ); - - if( pDet ) - { - maURL = rURL; - pDet->Release(); - pDet = NULL; - } - else - maURL = OUString(); - - return( maURL.getLength() > 0 ); + disposePipeline(); } -// ------------------------------------------------------------------------------ +FrameGrabber* FrameGrabber::create( const rtl::OUString &rURL ) +{ + return new FrameGrabber( rURL ); +} uno::Reference< graphic::XGraphic > SAL_CALL FrameGrabber::grabFrame( double fMediaTime ) throw (uno::RuntimeException) { uno::Reference< graphic::XGraphic > xRet; - IMediaDet* pDet = implCreateMediaDet( maURL ); - if( pDet ) - { - double fLength; - long nStreamCount; - bool bFound = false; - - if( SUCCEEDED( pDet->get_OutputStreams( &nStreamCount ) ) ) - { - for( long n = 0; ( n < nStreamCount ) && !bFound; ++n ) - { - GUID aMajorType; + if( !mpPipeline ) + return xRet; - if( SUCCEEDED( pDet->put_CurrentStream( n ) ) && - SUCCEEDED( pDet->get_StreamType( &aMajorType ) ) && - ( aMajorType == MEDIATYPE_Video ) ) - { - bFound = true; - } - } - } + gint64 gst_position = llround( fMediaTime * 1E9 ); + gst_element_seek_simple( + mpPipeline, GST_FORMAT_TIME, + (GstSeekFlags)(GST_SEEK_FLAG_KEY_UNIT | GST_SEEK_FLAG_FLUSH), + gst_position ); - if( bFound && - ( S_OK == pDet->get_StreamLength( &fLength ) ) && - ( fLength > 0.0 ) && ( fMediaTime >= 0.0 ) && ( fMediaTime <= fLength ) ) - { - AM_MEDIA_TYPE aMediaType; - long nWidth = 0, nHeight = 0, nSize = 0; + GstElement *pSink = gst_bin_get_by_name( GST_BIN( mpPipeline ), "sink" ); + if( !pSink ) + return xRet; - if( SUCCEEDED( pDet->get_StreamMediaType( &aMediaType ) ) ) - { - if( ( aMediaType.formattype == FORMAT_VideoInfo ) && - ( aMediaType.cbFormat >= sizeof( VIDEOINFOHEADER ) ) ) - { - VIDEOINFOHEADER* pVih = reinterpret_cast< VIDEOINFOHEADER* >( aMediaType.pbFormat ); + GstBuffer *pBuf = NULL; + GstCaps *pCaps = NULL; - nWidth = pVih->bmiHeader.biWidth; - nHeight = pVih->bmiHeader.biHeight; + // synchronously fetch the frame +#ifdef AVMEDIA_GST_0_10 + g_signal_emit_by_name( pSink, "pull-preroll", &pBuf, NULL ); + if( pBuf ) + pCaps = GST_BUFFER_CAPS( pBuf ); +#else + GstSample *pSample = NULL; + g_signal_emit_by_name( pSink, "pull-preroll", &pSample, NULL ); - if( nHeight < 0 ) - nHeight *= -1; - } + if( pSample ) + { + pBuf = gst_sample_get_buffer( pSample ); + pCaps = gst_sample_get_caps( pSample ); + } +#endif - if( aMediaType.cbFormat != 0 ) - { - ::CoTaskMemFree( (PVOID) aMediaType.pbFormat ); - aMediaType.cbFormat = 0; - aMediaType.pbFormat = NULL; - } + // get geometry + int nWidth = 0, nHeight = 0; + if( !pCaps ) + g_warning( "could not get snapshot format\n" ); + else + { + GstStructure *pStruct = gst_caps_get_structure( pCaps, 0 ); - if( aMediaType.pUnk != NULL ) - { - aMediaType.pUnk->Release(); - aMediaType.pUnk = NULL; - } - } + /* we need to get the final caps on the buffer to get the size */ + if( !gst_structure_get_int( pStruct, "width", &nWidth ) || + !gst_structure_get_int( pStruct, "height", &nHeight ) ) + nWidth = nHeight = 0; + } - if( ( nWidth > 0 ) && ( nHeight > 0 ) && - SUCCEEDED( pDet->GetBitmapBits( 0, &nSize, NULL, nWidth, nHeight ) ) && - ( nSize > 0 ) ) + if( pBuf && nWidth > 0 && nHeight > 0 && + // sanity check the size +#ifdef AVMEDIA_GST_0_10 + GST_BUFFER_SIZE( pBuf ) >= ( nWidth * nHeight * 3 ) +#else + gst_buffer_get_size( pBuf ) >= ( nWidth * nHeight * 3 ) +#endif + ) + { + sal_uInt8 *pData = NULL; +#ifdef AVMEDIA_GST_0_10 + pData = GST_BUFFER_DATA( pBuf ); +#else + GstMapInfo aMapInfo; + gst_buffer_map( pBuf, &aMapInfo, GST_MAP_READ ); + pData = aMapInfo.data; +#endif + + int nStride = GST_ROUND_UP_4( nWidth * 3 ); + Bitmap aBmp( Size( nWidth, nHeight ), 24 ); + + BitmapWriteAccess *pWrite = aBmp.AcquireWriteAccess(); + if( pWrite ) + { + // yet another cheesy pixel copying loop + for( int y = 0; y < nHeight; ++y ) { - char* pBuffer = new char[ nSize ]; - - try + sal_uInt8 *p = pData + y * nStride; + for( int x = 0; x < nWidth; ++x ) { - if( SUCCEEDED( pDet->GetBitmapBits( fMediaTime, NULL, pBuffer, nWidth, nHeight ) ) ) - { - SvMemoryStream aMemStm( pBuffer, nSize, STREAM_READ | STREAM_WRITE ); - Bitmap aBmp; - - if( aBmp.Read( aMemStm, false ) && !aBmp.IsEmpty() ) - { - const Graphic aGraphic( aBmp ); - xRet = aGraphic.GetXGraphic(); - } - } + BitmapColor col( p[0], p[1], p[2] ); + pWrite->SetPixel( y, x, col ); + p += 3; } - catch( ... ) - { - } - - delete [] pBuffer; } } + aBmp.ReleaseAccess( pWrite ); + +#ifndef AVMEDIA_GST_0_10 + gst_buffer_unmap( pBuf, &aMapInfo ); +#endif - pDet->Release(); + xRet = Graphic( aBmp ).GetXGraphic(); } return xRet; } -// ------------------------------------------------------------------------------ - -OUString SAL_CALL FrameGrabber::getImplementationName( ) +::rtl::OUString SAL_CALL FrameGrabber::getImplementationName( ) throw (uno::RuntimeException) { - return OUString( AVMEDIA_GST_FRAMEGRABBER_IMPLEMENTATIONNAME ); + return ::rtl::OUString( AVMEDIA_GST_FRAMEGRABBER_IMPLEMENTATIONNAME ); } -// ------------------------------------------------------------------------------ - -sal_Bool SAL_CALL FrameGrabber::supportsService( const OUString& ServiceName ) +sal_Bool SAL_CALL FrameGrabber::supportsService( const ::rtl::OUString& ServiceName ) throw (uno::RuntimeException) { return ServiceName == AVMEDIA_GST_FRAMEGRABBER_SERVICENAME; } -// ------------------------------------------------------------------------------ - -uno::Sequence< OUString > SAL_CALL FrameGrabber::getSupportedServiceNames( ) +uno::Sequence< ::rtl::OUString > SAL_CALL FrameGrabber::getSupportedServiceNames() throw (uno::RuntimeException) { - uno::Sequence< OUString > aRet(1); - aRet[0] = AVMEDIA_GST_FRAMEGRABBER_SERVICENAME ; + uno::Sequence< ::rtl::OUString > aRet(1); + aRet[0] = AVMEDIA_GST_FRAMEGRABBER_SERVICENAME; return aRet; } diff --git a/avmedia/source/gstreamer/gstframegrabber.hxx b/avmedia/source/gstreamer/gstframegrabber.hxx index a16317aa4eae..af23cca1ab7a 100644 --- a/avmedia/source/gstreamer/gstframegrabber.hxx +++ b/avmedia/source/gstreamer/gstframegrabber.hxx @@ -20,9 +20,9 @@ #ifndef _FRAMEGRABBER_HXX #define _FRAMEGRABBER_HXX -#include "gstcommon.hxx" - -#include "com/sun/star/media/XFrameGrabber.hpp" +#include "gstplayer.hxx" +#include "com/sun/star/media/XFrameGrabber.hdl" +#include <cppuhelper/implbase2.hxx> namespace avmedia { namespace gstreamer { @@ -30,31 +30,34 @@ namespace avmedia { namespace gstreamer { // - FrameGrabber - // ---------------- -class FrameGrabber : public ::cppu::WeakImplHelper2 < ::com::sun::star::media::XFrameGrabber, - ::com::sun::star::lang::XServiceInfo > +typedef ::cppu::WeakImplHelper2< ::com::sun::star::media::XFrameGrabber, + ::com::sun::star::lang::XServiceInfo > FrameGrabber_BASE; + +class FrameGrabber : public FrameGrabber_BASE { + GstElement *mpPipeline; + void disposePipeline(); public: + // static create method instead of public Ctor + static FrameGrabber* create( const rtl::OUString &rURL ); - FrameGrabber( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxMgr ); - ~FrameGrabber(); - - bool create( const OUString& rURL ); + virtual ~FrameGrabber(); // XFrameGrabber virtual ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic > SAL_CALL grabFrame( double fMediaTime ) throw (::com::sun::star::uno::RuntimeException); // XServiceInfo - virtual OUString SAL_CALL getImplementationName( ) throw (::com::sun::star::uno::RuntimeException); - virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException); - virtual ::com::sun::star::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException); private: - - ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxMgr; - OUString maURL; + FrameGrabber( const rtl::OUString &aURL ); + FrameGrabber( const FrameGrabber& ); + FrameGrabber& operator=( const FrameGrabber& ); }; -} // namespace gstreamer +} // namespace gst } // namespace avmedia #endif // _FRAMEGRABBER_HXX diff --git a/avmedia/source/gstreamer/gstplayer.cxx b/avmedia/source/gstreamer/gstplayer.cxx index b8b1ceb7246a..6e002301194d 100644 --- a/avmedia/source/gstreamer/gstplayer.cxx +++ b/avmedia/source/gstreamer/gstplayer.cxx @@ -28,13 +28,15 @@ #include "gstframegrabber.hxx" #include "gstwindow.hxx" -#ifndef AVMEDIA_GST_0_10 +#ifdef AVMEDIA_GST_0_10 +# define AVMEDIA_GST_PLAYER_IMPLEMENTATIONNAME "com.sun.star.comp.avmedia.Player_GStreamer_0_10" +# define AVMEDIA_GST_PLAYER_SERVICENAME "com.sun.star.media.Player_GStreamer_0_10" +#else # 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" #endif -#define AVMEDIA_GST_PLAYER_IMPLEMENTATIONNAME "com.sun.star.comp.avmedia.Player_GStreamer" -#define AVMEDIA_GST_PLAYER_SERVICENAME "com.sun.star.media.Player_GStreamer" - #ifdef AVMEDIA_GST_0_10 # define AVVERSION "gst 0.10: " #else @@ -58,6 +60,7 @@ namespace avmedia { namespace gstreamer { // ---------------- Player::Player( const uno::Reference< lang::XMultiServiceFactory >& rxMgr ) : + GstPlayer_BASE( m_aMutex ), mxMgr( rxMgr ), mpPlaybin( NULL ), mbFakeVideo (sal_False ), @@ -96,6 +99,17 @@ Player::Player( const uno::Reference< lang::XMultiServiceFactory >& rxMgr ) : Player::~Player() { DBG( "%p Player::~Player", this ); + if( mbInitialized ) + disposing(); +} + +void SAL_CALL Player::disposing() +{ + ::osl::MutexGuard aGuard(m_aMutex); + + stop(); + + DBG( "%p Player::disposing", this ); // Release the elements and pipeline if( mbInitialized ) @@ -204,7 +218,7 @@ GstBusSyncReply Player::processSyncMessage( GstMessage *message ) #endif { DBG( "%p processSyncMessage prepare window id: %s %d", this, - GST_MESSAGE_TYPE_NAME( message ), (int)mnWindowId ); + 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, NULL ); @@ -316,7 +330,7 @@ GstBusSyncReply Player::processSyncMessage( GstMessage *message ) return GST_BUS_PASS; } -void Player::preparePlaybin( const OUString& rURL, bool bFakeVideo ) +void Player::preparePlaybin( const OUString& rURL, GstElement *pSink ) { GstBus *pBus; @@ -327,11 +341,13 @@ void Player::preparePlaybin( const OUString& rURL, bool bFakeVideo ) } mpPlaybin = gst_element_factory_make( "playbin", NULL ); - if( bFakeVideo ) // used for getting prefered size etc. - g_object_set( G_OBJECT( mpPlaybin ), "video-sink", - gst_element_factory_make( "fakesink", NULL ), NULL ); - - mbFakeVideo = bFakeVideo; + if( pSink != NULL ) // used for getting prefered size etc. + { + g_object_set( G_OBJECT( mpPlaybin ), "video-sink", pSink, NULL ); + mbFakeVideo = true; + } + else + mbFakeVideo = false; rtl::OString ascURL = OUStringToOString( rURL, RTL_TEXTENCODING_UTF8 ); g_object_set( G_OBJECT( mpPlaybin ), "uri", ascURL.getStr() , NULL ); @@ -355,9 +371,10 @@ bool Player::create( const OUString& rURL ) DBG("create player, URL: %s", OUStringToOString( rURL, RTL_TEXTENCODING_UTF8 ).getStr()); - if( mbInitialized ) + if( mbInitialized && !rURL.isEmpty() ) { - preparePlaybin( rURL, true ); + // fakesink for pre-roll & sizing ... + preparePlaybin( rURL, gst_element_factory_make( "fakesink", NULL ) ); gst_element_set_state( mpPlaybin, GST_STATE_PAUSED ); mbPlayPending = false; @@ -378,6 +395,8 @@ bool Player::create( const OUString& rURL ) void SAL_CALL Player::start() throw (uno::RuntimeException) { + ::osl::MutexGuard aGuard(m_aMutex); + // set the pipeline state to READY and run the loop if( mbInitialized && NULL != mpPlaybin ) { @@ -391,6 +410,8 @@ void SAL_CALL Player::start() void SAL_CALL Player::stop() throw (uno::RuntimeException) { + ::osl::MutexGuard aGuard(m_aMutex); + // set the pipeline in PAUSED STATE if( mpPlaybin ) gst_element_set_state( mpPlaybin, GST_STATE_PAUSED ); @@ -404,6 +425,8 @@ void SAL_CALL Player::stop() sal_Bool SAL_CALL Player::isPlaying() throw (uno::RuntimeException) { + ::osl::MutexGuard aGuard(m_aMutex); + bool bRet = mbPlayPending; // return whether the pipeline is in PLAYING STATE or not @@ -422,6 +445,8 @@ sal_Bool SAL_CALL Player::isPlaying() double SAL_CALL Player::getDuration() throw (uno::RuntimeException) { + ::osl::MutexGuard aGuard(m_aMutex); + // slideshow checks for non-zero duration, so cheat here double duration = 0.01; @@ -437,6 +462,8 @@ double SAL_CALL Player::getDuration() void SAL_CALL Player::setMediaTime( double fTime ) throw (uno::RuntimeException) { + ::osl::MutexGuard aGuard(m_aMutex); + if( mpPlaybin ) { gint64 gst_position = llround (fTime * 1E9); @@ -457,6 +484,8 @@ void SAL_CALL Player::setMediaTime( double fTime ) double SAL_CALL Player::getMediaTime() throw (uno::RuntimeException) { + ::osl::MutexGuard aGuard(m_aMutex); + double position = 0.0; if( mpPlaybin ) { @@ -474,13 +503,12 @@ double SAL_CALL Player::getMediaTime() double SAL_CALL Player::getRate() throw (uno::RuntimeException) { - double rate = 0.0; + ::osl::MutexGuard aGuard(m_aMutex); - // TODO get the window rate - if( mbInitialized ) - { + double rate = 1.0; - } + // TODO get the window rate - but no need since + // higher levels never set rate > 1 return rate; } @@ -490,6 +518,7 @@ double SAL_CALL Player::getRate() void SAL_CALL Player::setPlaybackLoop( sal_Bool bSet ) throw (uno::RuntimeException) { + ::osl::MutexGuard aGuard(m_aMutex); // TODO check how to do with GST mbLooping = bSet; } @@ -499,6 +528,7 @@ void SAL_CALL Player::setPlaybackLoop( sal_Bool bSet ) sal_Bool SAL_CALL Player::isPlaybackLoop() throw (uno::RuntimeException) { + ::osl::MutexGuard aGuard(m_aMutex); // TODO check how to do with GST return mbLooping; } @@ -508,6 +538,8 @@ sal_Bool SAL_CALL Player::isPlaybackLoop() void SAL_CALL Player::setMute( sal_Bool bSet ) throw (uno::RuntimeException) { + ::osl::MutexGuard aGuard(m_aMutex); + DBG( "set mute: %d muted: %d unmuted volume: %lf", bSet, mbMuted, mnUnmutedVolume ); // change the volume to 0 or the unmuted volume @@ -530,6 +562,8 @@ void SAL_CALL Player::setMute( sal_Bool bSet ) sal_Bool SAL_CALL Player::isMute() throw (uno::RuntimeException) { + ::osl::MutexGuard aGuard(m_aMutex); + return mbMuted; } @@ -538,6 +572,8 @@ sal_Bool SAL_CALL Player::isMute() void SAL_CALL Player::setVolumeDB( sal_Int16 nVolumeDB ) throw (uno::RuntimeException) { + ::osl::MutexGuard aGuard(m_aMutex); + mnUnmutedVolume = pow( 10.0, nVolumeDB / 20.0 ); DBG( "set volume: %d gst volume: %lf", nVolumeDB, mnUnmutedVolume ); @@ -554,6 +590,8 @@ void SAL_CALL Player::setVolumeDB( sal_Int16 nVolumeDB ) sal_Int16 SAL_CALL Player::getVolumeDB() throw (uno::RuntimeException) { + ::osl::MutexGuard aGuard(m_aMutex); + sal_Int16 nVolumeDB(0); if( mpPlaybin ) { @@ -572,9 +610,17 @@ sal_Int16 SAL_CALL Player::getVolumeDB() awt::Size SAL_CALL Player::getPreferredPlayerWindowSize() throw (uno::RuntimeException) { + ::osl::MutexGuard aGuard(m_aMutex); + awt::Size aSize( 0, 0 ); - DBG( "%p Player::getPreferredPlayerWindowSize, member %d x %d", this, mnWidth, mnHeight ); + if( maURL.isEmpty() ) + { + DBG( "%p Player::getPreferredPlayerWindowSize - empty URL => 0x0", this ); + return aSize; + } + + DBG( "%p pre-Player::getPreferredPlayerWindowSize, member %d x %d", this, mnWidth, mnHeight ); TimeValue aTimeout = { 10, 0 }; #if OSL_DEBUG_LEVEL > 2 @@ -582,9 +628,6 @@ awt::Size SAL_CALL Player::getPreferredPlayerWindowSize() #endif maSizeCondition.wait( &aTimeout ); - if( mbFakeVideo ) // ready ourselves for the real thing - preparePlaybin( maURL, false ); - DBG( "%p Player::getPreferredPlayerWindowSize after waitCondition %d, member %d x %d", this, aResult, mnWidth, mnHeight ); if( mnWidth != 0 && mnHeight != 0 ) { @@ -600,9 +643,14 @@ awt::Size SAL_CALL Player::getPreferredPlayerWindowSize() uno::Reference< ::media::XPlayerWindow > SAL_CALL Player::createPlayerWindow( const uno::Sequence< uno::Any >& rArguments ) throw (uno::RuntimeException) { + ::osl::MutexGuard aGuard(m_aMutex); + uno::Reference< ::media::XPlayerWindow > xRet; awt::Size aSize( getPreferredPlayerWindowSize() ); + if( mbFakeVideo ) + preparePlaybin( maURL, NULL ); + DBG( "Player::createPlayerWindow %d %d length: %d", aSize.Width, aSize.Height, rArguments.getLength() ); if( aSize.Width > 0 && aSize.Height > 0 ) @@ -637,9 +685,15 @@ uno::Reference< ::media::XPlayerWindow > SAL_CALL Player::createPlayerWindow( co uno::Reference< media::XFrameGrabber > SAL_CALL Player::createFrameGrabber() throw (uno::RuntimeException) { - uno::Reference< media::XFrameGrabber > xRet; + ::osl::MutexGuard aGuard(m_aMutex); + FrameGrabber* pFrameGrabber = NULL; + const awt::Size aPrefSize( getPreferredPlayerWindowSize() ); - return xRet; + if( ( aPrefSize.Width > 0 ) && ( aPrefSize.Height > 0 ) ) + pFrameGrabber = FrameGrabber::create( maURL ); + DBG( "created FrameGrabber %p", pFrameGrabber ); + + return pFrameGrabber; } // ------------------------------------------------------------------------------ diff --git a/avmedia/source/gstreamer/gstplayer.hxx b/avmedia/source/gstreamer/gstplayer.hxx index 82a93e8fa984..5a84a0095689 100644 --- a/avmedia/source/gstreamer/gstplayer.hxx +++ b/avmedia/source/gstreamer/gstplayer.hxx @@ -24,6 +24,8 @@ #include "gstcommon.hxx" #include "com/sun/star/media/XPlayer.hpp" +#include <cppuhelper/compbase2.hxx> +#include <cppuhelper/basemutex.hxx> typedef struct _GstVideoOverlay GstVideoOverlay; @@ -33,18 +35,21 @@ namespace avmedia { namespace gstreamer { // - Player - // ---------- -class Player : public ::cppu::WeakImplHelper2< ::com::sun::star::media::XPlayer, - ::com::sun::star::lang::XServiceInfo > +typedef ::cppu::WeakComponentImplHelper2< ::com::sun::star::media::XPlayer, + ::com::sun::star::lang::XServiceInfo > GstPlayer_BASE; + +class Player : public ::cppu::BaseMutex, + public GstPlayer_BASE { public: Player( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxMgr ); ~Player(); - void preparePlaybin( const OUString& rURL, bool bFakeVideo ); + void preparePlaybin( const OUString& rURL, GstElement *pSink ); bool create( const OUString& rURL ); - void processMessage( GstMessage *message ); - GstBusSyncReply processSyncMessage( GstMessage *message ); + virtual void processMessage( GstMessage *message ); + virtual GstBusSyncReply processSyncMessage( GstMessage *message ); // XPlayer virtual void SAL_CALL start( ) throw (::com::sun::star::uno::RuntimeException); @@ -69,8 +74,10 @@ public: virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException); virtual ::com::sun::star::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException); -private: + // ::cppu::OComponentHelper + virtual void SAL_CALL disposing(void); +protected: ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxMgr; OUString maURL; |