Kaydet (Commit) fc6351f5 authored tarafından Michael Meeks's avatar Michael Meeks

avmedia: first cut at gstreamer frame grabber.

with thanks to Tim-Philipp Müller and Wim Taymans.

Change-Id: Ia095d06ea3cbed85570cc33038f98da0362c1e62
üst 3e46a434
...@@ -60,6 +60,7 @@ $(eval $(call gb_Library_add_exception_objects,avmediagst,\ ...@@ -60,6 +60,7 @@ $(eval $(call gb_Library_add_exception_objects,avmediagst,\
avmedia/source/gstreamer/gstplayer \ avmedia/source/gstreamer/gstplayer \
avmedia/source/gstreamer/gstuno \ avmedia/source/gstreamer/gstuno \
avmedia/source/gstreamer/gstwindow \ avmedia/source/gstreamer/gstwindow \
avmedia/source/gstreamer/gstframegrabber \
)) ))
# vim: set noet sw=4 ts=4: # vim: set noet sw=4 ts=4:
...@@ -21,3 +21,4 @@ ...@@ -21,3 +21,4 @@
#include "gstplayer.cxx" #include "gstplayer.cxx"
#include "gstuno.cxx" #include "gstuno.cxx"
#include "gstwindow.cxx" #include "gstwindow.cxx"
#include "gstframegrabber.cxx"
...@@ -17,206 +17,207 @@ ...@@ -17,206 +17,207 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 . * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/ */
#include <objbase.h> #include "gstframegrabber.hxx"
#include <strmif.h> #include "gstplayer.hxx"
#include <Amvideo.h>
#include <Qedit.h>
#include <uuids.h>
#include "framegrabber.hxx" #include <gst/gstbuffer.h>
#include "player.hxx" #include <gst/video/video.h>
#include <gst/video/gstvideosink.h>
#include <tools/stream.hxx>
#include <vcl/graph.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" #include <string>
#define AVMEDIA_GST_FRAMEGRABBER_SERVICENAME "com.sun.star.media.FrameGrabber_GStreamer"
#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; using namespace ::com::sun::star;
namespace avmedia { namespace gstreamer { namespace avmedia { namespace gstreamer {
// ---------------- void FrameGrabber::disposePipeline()
// - FrameGrabber -
// ----------------
FrameGrabber::FrameGrabber( const uno::Reference< lang::XMultiServiceFactory >& rxMgr ) :
mxMgr( rxMgr )
{
::CoInitialize( NULL );
}
// ------------------------------------------------------------------------------
FrameGrabber::~FrameGrabber()
{ {
::CoUninitialize(); if( mpPipeline != NULL )
{
gst_element_set_state( mpPipeline, GST_STATE_NULL );
g_object_unref( G_OBJECT( mpPipeline ) );
mpPipeline = NULL;
}
} }
// ------------------------------------------------------------------------------ FrameGrabber::FrameGrabber( const rtl::OUString &rURL ) :
FrameGrabber_BASE()
IMediaDet* FrameGrabber::implCreateMediaDet( const OUString& rURL ) const
{ {
IMediaDet* pDet = NULL; gchar *pPipelineStr;
pPipelineStr = g_strdup_printf(
if( SUCCEEDED( CoCreateInstance( CLSID_MediaDet, NULL, CLSCTX_INPROC_SERVER, IID_IMediaDet, (void**) &pDet ) ) ) #ifdef AVMEDIA_GST_0_10
{ "uridecodebin uri=%s ! ffmpegcolorspace ! videoscale ! appsink "
String aLocalStr; "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( mpPipeline ) {
{ // pre-roll
if( !SUCCEEDED( pDet->put_Filename( ::SysAllocString( aLocalStr.GetBuffer() ) ) ) ) switch( gst_element_set_state( mpPipeline, GST_STATE_PAUSED ) ) {
{ case GST_STATE_CHANGE_FAILURE:
pDet->Release(); case GST_STATE_CHANGE_NO_PREROLL:
pDet = NULL; g_warning( "failure pre-rolling media" );
} disposePipeline();
break;
default:
break;
} }
} }
if( mpPipeline &&
return pDet; gst_element_get_state( mpPipeline, NULL, NULL, 5 * GST_SECOND ) == GST_STATE_CHANGE_FAILURE )
disposePipeline();
} }
// ------------------------------------------------------------------------------ FrameGrabber::~FrameGrabber()
bool FrameGrabber::create( const OUString& rURL )
{ {
// just check if a MediaDet interface can be created with the given URL disposePipeline();
IMediaDet* pDet = implCreateMediaDet( rURL );
if( pDet )
{
maURL = rURL;
pDet->Release();
pDet = NULL;
}
else
maURL = OUString();
return( maURL.getLength() > 0 );
} }
// ------------------------------------------------------------------------------ FrameGrabber* FrameGrabber::create( const rtl::OUString &rURL )
{
return new FrameGrabber( rURL );
}
uno::Reference< graphic::XGraphic > SAL_CALL FrameGrabber::grabFrame( double fMediaTime ) uno::Reference< graphic::XGraphic > SAL_CALL FrameGrabber::grabFrame( double fMediaTime )
throw (uno::RuntimeException) throw (uno::RuntimeException)
{ {
uno::Reference< graphic::XGraphic > xRet; uno::Reference< graphic::XGraphic > xRet;
IMediaDet* pDet = implCreateMediaDet( maURL );
if( pDet ) if( !mpPipeline )
{ return xRet;
double fLength;
long nStreamCount;
bool bFound = false;
if( SUCCEEDED( pDet->get_OutputStreams( &nStreamCount ) ) )
{
for( long n = 0; ( n < nStreamCount ) && !bFound; ++n )
{
GUID aMajorType;
if( SUCCEEDED( pDet->put_CurrentStream( n ) ) && gint64 gst_position = llround( fMediaTime * 1E9 );
SUCCEEDED( pDet->get_StreamType( &aMajorType ) ) && gst_element_seek_simple(
( aMajorType == MEDIATYPE_Video ) ) mpPipeline, GST_FORMAT_TIME,
{ (GstSeekFlags)(GST_SEEK_FLAG_KEY_UNIT | GST_SEEK_FLAG_FLUSH),
bFound = true; gst_position );
}
}
}
if( bFound && GstElement *pSink = gst_bin_get_by_name( GST_BIN( mpPipeline ), "sink" );
( S_OK == pDet->get_StreamLength( &fLength ) ) && if( !pSink )
( fLength > 0.0 ) && ( fMediaTime >= 0.0 ) && ( fMediaTime <= fLength ) ) return xRet;
{
AM_MEDIA_TYPE aMediaType;
long nWidth = 0, nHeight = 0, nSize = 0;
if( SUCCEEDED( pDet->get_StreamMediaType( &aMediaType ) ) ) GstBuffer *pBuf = NULL;
{ GstCaps *pCaps = NULL;
if( ( aMediaType.formattype == FORMAT_VideoInfo ) &&
( aMediaType.cbFormat >= sizeof( VIDEOINFOHEADER ) ) )
{
VIDEOINFOHEADER* pVih = reinterpret_cast< VIDEOINFOHEADER* >( aMediaType.pbFormat );
nWidth = pVih->bmiHeader.biWidth; // synchronously fetch the frame
nHeight = pVih->bmiHeader.biHeight; #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 ) if( pSample )
nHeight *= -1; {
} pBuf = gst_sample_get_buffer( pSample );
pCaps = gst_sample_get_caps( pSample );
}
#endif
if( aMediaType.cbFormat != 0 ) // get geometry
{ int nWidth = 0, nHeight = 0;
::CoTaskMemFree( (PVOID) aMediaType.pbFormat ); if( !pCaps )
aMediaType.cbFormat = 0; g_warning( "could not get snapshot format\n" );
aMediaType.pbFormat = NULL; else
} {
GstStructure *pStruct = gst_caps_get_structure( pCaps, 0 );
if( 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 ) ||
aMediaType.pUnk->Release(); !gst_structure_get_int( pStruct, "height", &nHeight ) )
aMediaType.pUnk = NULL; nWidth = nHeight = 0;
} }
}
if( ( nWidth > 0 ) && ( nHeight > 0 ) && if( pBuf && nWidth > 0 && nHeight > 0 &&
SUCCEEDED( pDet->GetBitmapBits( 0, &nSize, NULL, nWidth, nHeight ) ) && // sanity check the size
( nSize > 0 ) ) #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 ]; sal_uInt8 *p = pData + y * nStride;
for( int x = 0; x < nWidth; ++x )
try
{ {
if( SUCCEEDED( pDet->GetBitmapBits( fMediaTime, NULL, pBuffer, nWidth, nHeight ) ) ) BitmapColor col( p[0], p[1], p[2] );
{ pWrite->SetPixel( y, x, col );
SvMemoryStream aMemStm( pBuffer, nSize, STREAM_READ | STREAM_WRITE ); p += 3;
Bitmap aBmp;
if( aBmp.Read( aMemStm, false ) && !aBmp.IsEmpty() )
{
const Graphic aGraphic( aBmp );
xRet = aGraphic.GetXGraphic();
}
}
} }
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; return xRet;
} }
// ------------------------------------------------------------------------------ ::rtl::OUString SAL_CALL FrameGrabber::getImplementationName( )
OUString SAL_CALL FrameGrabber::getImplementationName( )
throw (uno::RuntimeException) throw (uno::RuntimeException)
{ {
return OUString( AVMEDIA_GST_FRAMEGRABBER_IMPLEMENTATIONNAME ); return ::rtl::OUString( AVMEDIA_GST_FRAMEGRABBER_IMPLEMENTATIONNAME );
} }
// ------------------------------------------------------------------------------ sal_Bool SAL_CALL FrameGrabber::supportsService( const ::rtl::OUString& ServiceName )
sal_Bool SAL_CALL FrameGrabber::supportsService( const OUString& ServiceName )
throw (uno::RuntimeException) throw (uno::RuntimeException)
{ {
return ServiceName == AVMEDIA_GST_FRAMEGRABBER_SERVICENAME; return ServiceName == AVMEDIA_GST_FRAMEGRABBER_SERVICENAME;
} }
// ------------------------------------------------------------------------------ uno::Sequence< ::rtl::OUString > SAL_CALL FrameGrabber::getSupportedServiceNames()
uno::Sequence< OUString > SAL_CALL FrameGrabber::getSupportedServiceNames( )
throw (uno::RuntimeException) throw (uno::RuntimeException)
{ {
uno::Sequence< OUString > aRet(1); uno::Sequence< ::rtl::OUString > aRet(1);
aRet[0] = AVMEDIA_GST_FRAMEGRABBER_SERVICENAME ; aRet[0] = AVMEDIA_GST_FRAMEGRABBER_SERVICENAME;
return aRet; return aRet;
} }
......
...@@ -20,9 +20,9 @@ ...@@ -20,9 +20,9 @@
#ifndef _FRAMEGRABBER_HXX #ifndef _FRAMEGRABBER_HXX
#define _FRAMEGRABBER_HXX #define _FRAMEGRABBER_HXX
#include "gstcommon.hxx" #include "gstplayer.hxx"
#include "com/sun/star/media/XFrameGrabber.hdl"
#include "com/sun/star/media/XFrameGrabber.hpp" #include <cppuhelper/implbase2.hxx>
namespace avmedia { namespace gstreamer { namespace avmedia { namespace gstreamer {
...@@ -30,31 +30,34 @@ namespace avmedia { namespace gstreamer { ...@@ -30,31 +30,34 @@ namespace avmedia { namespace gstreamer {
// - FrameGrabber - // - FrameGrabber -
// ---------------- // ----------------
class FrameGrabber : public ::cppu::WeakImplHelper2 < ::com::sun::star::media::XFrameGrabber, typedef ::cppu::WeakImplHelper2< ::com::sun::star::media::XFrameGrabber,
::com::sun::star::lang::XServiceInfo > ::com::sun::star::lang::XServiceInfo > FrameGrabber_BASE;
class FrameGrabber : public FrameGrabber_BASE
{ {
GstElement *mpPipeline;
void disposePipeline();
public: 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 ); virtual ~FrameGrabber();
~FrameGrabber();
bool create( const OUString& rURL );
// XFrameGrabber // XFrameGrabber
virtual ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic > SAL_CALL grabFrame( double fMediaTime ) throw (::com::sun::star::uno::RuntimeException); virtual ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic > SAL_CALL grabFrame( double fMediaTime ) throw (::com::sun::star::uno::RuntimeException);
// XServiceInfo // XServiceInfo
virtual OUString SAL_CALL getImplementationName( ) 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 OUString& ServiceName ) 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< OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException); virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException);
private: private:
FrameGrabber( const rtl::OUString &aURL );
::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxMgr; FrameGrabber( const FrameGrabber& );
OUString maURL; FrameGrabber& operator=( const FrameGrabber& );
}; };
} // namespace gstreamer } // namespace gst
} // namespace avmedia } // namespace avmedia
#endif // _FRAMEGRABBER_HXX #endif // _FRAMEGRABBER_HXX
......
...@@ -28,13 +28,15 @@ ...@@ -28,13 +28,15 @@
#include "gstframegrabber.hxx" #include "gstframegrabber.hxx"
#include "gstwindow.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> # 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 #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 #ifdef AVMEDIA_GST_0_10
# define AVVERSION "gst 0.10: " # define AVVERSION "gst 0.10: "
#else #else
...@@ -58,6 +60,7 @@ namespace avmedia { namespace gstreamer { ...@@ -58,6 +60,7 @@ namespace avmedia { namespace gstreamer {
// ---------------- // ----------------
Player::Player( const uno::Reference< lang::XMultiServiceFactory >& rxMgr ) : Player::Player( const uno::Reference< lang::XMultiServiceFactory >& rxMgr ) :
GstPlayer_BASE( m_aMutex ),
mxMgr( rxMgr ), mxMgr( rxMgr ),
mpPlaybin( NULL ), mpPlaybin( NULL ),
mbFakeVideo (sal_False ), mbFakeVideo (sal_False ),
...@@ -96,6 +99,17 @@ Player::Player( const uno::Reference< lang::XMultiServiceFactory >& rxMgr ) : ...@@ -96,6 +99,17 @@ Player::Player( const uno::Reference< lang::XMultiServiceFactory >& rxMgr ) :
Player::~Player() Player::~Player()
{ {
DBG( "%p Player::~Player", this ); 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 // Release the elements and pipeline
if( mbInitialized ) if( mbInitialized )
...@@ -204,7 +218,7 @@ GstBusSyncReply Player::processSyncMessage( GstMessage *message ) ...@@ -204,7 +218,7 @@ GstBusSyncReply Player::processSyncMessage( GstMessage *message )
#endif #endif
{ {
DBG( "%p processSyncMessage prepare window id: %s %d", this, 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 ) if( mpXOverlay )
g_object_unref( G_OBJECT ( mpXOverlay ) ); g_object_unref( G_OBJECT ( mpXOverlay ) );
g_object_set( GST_MESSAGE_SRC( message ), "force-aspect-ratio", FALSE, NULL ); g_object_set( GST_MESSAGE_SRC( message ), "force-aspect-ratio", FALSE, NULL );
...@@ -316,7 +330,7 @@ GstBusSyncReply Player::processSyncMessage( GstMessage *message ) ...@@ -316,7 +330,7 @@ GstBusSyncReply Player::processSyncMessage( GstMessage *message )
return GST_BUS_PASS; return GST_BUS_PASS;
} }
void Player::preparePlaybin( const OUString& rURL, bool bFakeVideo ) void Player::preparePlaybin( const OUString& rURL, GstElement *pSink )
{ {
GstBus *pBus; GstBus *pBus;
...@@ -327,11 +341,13 @@ void Player::preparePlaybin( const OUString& rURL, bool bFakeVideo ) ...@@ -327,11 +341,13 @@ void Player::preparePlaybin( const OUString& rURL, bool bFakeVideo )
} }
mpPlaybin = gst_element_factory_make( "playbin", NULL ); mpPlaybin = gst_element_factory_make( "playbin", NULL );
if( bFakeVideo ) // used for getting prefered size etc. if( pSink != NULL ) // used for getting prefered size etc.
g_object_set( G_OBJECT( mpPlaybin ), "video-sink", {
gst_element_factory_make( "fakesink", NULL ), NULL ); g_object_set( G_OBJECT( mpPlaybin ), "video-sink", pSink, NULL );
mbFakeVideo = true;
mbFakeVideo = bFakeVideo; }
else
mbFakeVideo = false;
rtl::OString ascURL = OUStringToOString( rURL, RTL_TEXTENCODING_UTF8 ); rtl::OString ascURL = OUStringToOString( rURL, RTL_TEXTENCODING_UTF8 );
g_object_set( G_OBJECT( mpPlaybin ), "uri", ascURL.getStr() , NULL ); g_object_set( G_OBJECT( mpPlaybin ), "uri", ascURL.getStr() , NULL );
...@@ -355,9 +371,10 @@ bool Player::create( const OUString& rURL ) ...@@ -355,9 +371,10 @@ bool Player::create( const OUString& rURL )
DBG("create player, URL: %s", OUStringToOString( rURL, RTL_TEXTENCODING_UTF8 ).getStr()); 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 ); gst_element_set_state( mpPlaybin, GST_STATE_PAUSED );
mbPlayPending = false; mbPlayPending = false;
...@@ -378,6 +395,8 @@ bool Player::create( const OUString& rURL ) ...@@ -378,6 +395,8 @@ bool Player::create( const OUString& rURL )
void SAL_CALL Player::start() void SAL_CALL Player::start()
throw (uno::RuntimeException) throw (uno::RuntimeException)
{ {
::osl::MutexGuard aGuard(m_aMutex);
// set the pipeline state to READY and run the loop // set the pipeline state to READY and run the loop
if( mbInitialized && NULL != mpPlaybin ) if( mbInitialized && NULL != mpPlaybin )
{ {
...@@ -391,6 +410,8 @@ void SAL_CALL Player::start() ...@@ -391,6 +410,8 @@ void SAL_CALL Player::start()
void SAL_CALL Player::stop() void SAL_CALL Player::stop()
throw (uno::RuntimeException) throw (uno::RuntimeException)
{ {
::osl::MutexGuard aGuard(m_aMutex);
// set the pipeline in PAUSED STATE // set the pipeline in PAUSED STATE
if( mpPlaybin ) if( mpPlaybin )
gst_element_set_state( mpPlaybin, GST_STATE_PAUSED ); gst_element_set_state( mpPlaybin, GST_STATE_PAUSED );
...@@ -404,6 +425,8 @@ void SAL_CALL Player::stop() ...@@ -404,6 +425,8 @@ void SAL_CALL Player::stop()
sal_Bool SAL_CALL Player::isPlaying() sal_Bool SAL_CALL Player::isPlaying()
throw (uno::RuntimeException) throw (uno::RuntimeException)
{ {
::osl::MutexGuard aGuard(m_aMutex);
bool bRet = mbPlayPending; bool bRet = mbPlayPending;
// return whether the pipeline is in PLAYING STATE or not // return whether the pipeline is in PLAYING STATE or not
...@@ -422,6 +445,8 @@ sal_Bool SAL_CALL Player::isPlaying() ...@@ -422,6 +445,8 @@ sal_Bool SAL_CALL Player::isPlaying()
double SAL_CALL Player::getDuration() double SAL_CALL Player::getDuration()
throw (uno::RuntimeException) throw (uno::RuntimeException)
{ {
::osl::MutexGuard aGuard(m_aMutex);
// slideshow checks for non-zero duration, so cheat here // slideshow checks for non-zero duration, so cheat here
double duration = 0.01; double duration = 0.01;
...@@ -437,6 +462,8 @@ double SAL_CALL Player::getDuration() ...@@ -437,6 +462,8 @@ double SAL_CALL Player::getDuration()
void SAL_CALL Player::setMediaTime( double fTime ) void SAL_CALL Player::setMediaTime( double fTime )
throw (uno::RuntimeException) throw (uno::RuntimeException)
{ {
::osl::MutexGuard aGuard(m_aMutex);
if( mpPlaybin ) { if( mpPlaybin ) {
gint64 gst_position = llround (fTime * 1E9); gint64 gst_position = llround (fTime * 1E9);
...@@ -457,6 +484,8 @@ void SAL_CALL Player::setMediaTime( double fTime ) ...@@ -457,6 +484,8 @@ void SAL_CALL Player::setMediaTime( double fTime )
double SAL_CALL Player::getMediaTime() double SAL_CALL Player::getMediaTime()
throw (uno::RuntimeException) throw (uno::RuntimeException)
{ {
::osl::MutexGuard aGuard(m_aMutex);
double position = 0.0; double position = 0.0;
if( mpPlaybin ) { if( mpPlaybin ) {
...@@ -474,13 +503,12 @@ double SAL_CALL Player::getMediaTime() ...@@ -474,13 +503,12 @@ double SAL_CALL Player::getMediaTime()
double SAL_CALL Player::getRate() double SAL_CALL Player::getRate()
throw (uno::RuntimeException) throw (uno::RuntimeException)
{ {
double rate = 0.0; ::osl::MutexGuard aGuard(m_aMutex);
// TODO get the window rate double rate = 1.0;
if( mbInitialized )
{
} // TODO get the window rate - but no need since
// higher levels never set rate > 1
return rate; return rate;
} }
...@@ -490,6 +518,7 @@ double SAL_CALL Player::getRate() ...@@ -490,6 +518,7 @@ double SAL_CALL Player::getRate()
void SAL_CALL Player::setPlaybackLoop( sal_Bool bSet ) void SAL_CALL Player::setPlaybackLoop( sal_Bool bSet )
throw (uno::RuntimeException) throw (uno::RuntimeException)
{ {
::osl::MutexGuard aGuard(m_aMutex);
// TODO check how to do with GST // TODO check how to do with GST
mbLooping = bSet; mbLooping = bSet;
} }
...@@ -499,6 +528,7 @@ void SAL_CALL Player::setPlaybackLoop( sal_Bool bSet ) ...@@ -499,6 +528,7 @@ void SAL_CALL Player::setPlaybackLoop( sal_Bool bSet )
sal_Bool SAL_CALL Player::isPlaybackLoop() sal_Bool SAL_CALL Player::isPlaybackLoop()
throw (uno::RuntimeException) throw (uno::RuntimeException)
{ {
::osl::MutexGuard aGuard(m_aMutex);
// TODO check how to do with GST // TODO check how to do with GST
return mbLooping; return mbLooping;
} }
...@@ -508,6 +538,8 @@ sal_Bool SAL_CALL Player::isPlaybackLoop() ...@@ -508,6 +538,8 @@ sal_Bool SAL_CALL Player::isPlaybackLoop()
void SAL_CALL Player::setMute( sal_Bool bSet ) void SAL_CALL Player::setMute( sal_Bool bSet )
throw (uno::RuntimeException) throw (uno::RuntimeException)
{ {
::osl::MutexGuard aGuard(m_aMutex);
DBG( "set mute: %d muted: %d unmuted volume: %lf", bSet, mbMuted, mnUnmutedVolume ); DBG( "set mute: %d muted: %d unmuted volume: %lf", bSet, mbMuted, mnUnmutedVolume );
// change the volume to 0 or the unmuted volume // change the volume to 0 or the unmuted volume
...@@ -530,6 +562,8 @@ void SAL_CALL Player::setMute( sal_Bool bSet ) ...@@ -530,6 +562,8 @@ void SAL_CALL Player::setMute( sal_Bool bSet )
sal_Bool SAL_CALL Player::isMute() sal_Bool SAL_CALL Player::isMute()
throw (uno::RuntimeException) throw (uno::RuntimeException)
{ {
::osl::MutexGuard aGuard(m_aMutex);
return mbMuted; return mbMuted;
} }
...@@ -538,6 +572,8 @@ sal_Bool SAL_CALL Player::isMute() ...@@ -538,6 +572,8 @@ sal_Bool SAL_CALL Player::isMute()
void SAL_CALL Player::setVolumeDB( sal_Int16 nVolumeDB ) void SAL_CALL Player::setVolumeDB( sal_Int16 nVolumeDB )
throw (uno::RuntimeException) throw (uno::RuntimeException)
{ {
::osl::MutexGuard aGuard(m_aMutex);
mnUnmutedVolume = pow( 10.0, nVolumeDB / 20.0 ); mnUnmutedVolume = pow( 10.0, nVolumeDB / 20.0 );
DBG( "set volume: %d gst volume: %lf", nVolumeDB, mnUnmutedVolume ); DBG( "set volume: %d gst volume: %lf", nVolumeDB, mnUnmutedVolume );
...@@ -554,6 +590,8 @@ void SAL_CALL Player::setVolumeDB( sal_Int16 nVolumeDB ) ...@@ -554,6 +590,8 @@ void SAL_CALL Player::setVolumeDB( sal_Int16 nVolumeDB )
sal_Int16 SAL_CALL Player::getVolumeDB() sal_Int16 SAL_CALL Player::getVolumeDB()
throw (uno::RuntimeException) throw (uno::RuntimeException)
{ {
::osl::MutexGuard aGuard(m_aMutex);
sal_Int16 nVolumeDB(0); sal_Int16 nVolumeDB(0);
if( mpPlaybin ) { if( mpPlaybin ) {
...@@ -572,9 +610,17 @@ sal_Int16 SAL_CALL Player::getVolumeDB() ...@@ -572,9 +610,17 @@ sal_Int16 SAL_CALL Player::getVolumeDB()
awt::Size SAL_CALL Player::getPreferredPlayerWindowSize() awt::Size SAL_CALL Player::getPreferredPlayerWindowSize()
throw (uno::RuntimeException) throw (uno::RuntimeException)
{ {
::osl::MutexGuard aGuard(m_aMutex);
awt::Size aSize( 0, 0 ); 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 }; TimeValue aTimeout = { 10, 0 };
#if OSL_DEBUG_LEVEL > 2 #if OSL_DEBUG_LEVEL > 2
...@@ -582,9 +628,6 @@ awt::Size SAL_CALL Player::getPreferredPlayerWindowSize() ...@@ -582,9 +628,6 @@ awt::Size SAL_CALL Player::getPreferredPlayerWindowSize()
#endif #endif
maSizeCondition.wait( &aTimeout ); 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 ); DBG( "%p Player::getPreferredPlayerWindowSize after waitCondition %d, member %d x %d", this, aResult, mnWidth, mnHeight );
if( mnWidth != 0 && mnHeight != 0 ) { if( mnWidth != 0 && mnHeight != 0 ) {
...@@ -600,9 +643,14 @@ awt::Size SAL_CALL Player::getPreferredPlayerWindowSize() ...@@ -600,9 +643,14 @@ awt::Size SAL_CALL Player::getPreferredPlayerWindowSize()
uno::Reference< ::media::XPlayerWindow > SAL_CALL Player::createPlayerWindow( const uno::Sequence< uno::Any >& rArguments ) uno::Reference< ::media::XPlayerWindow > SAL_CALL Player::createPlayerWindow( const uno::Sequence< uno::Any >& rArguments )
throw (uno::RuntimeException) throw (uno::RuntimeException)
{ {
::osl::MutexGuard aGuard(m_aMutex);
uno::Reference< ::media::XPlayerWindow > xRet; uno::Reference< ::media::XPlayerWindow > xRet;
awt::Size aSize( getPreferredPlayerWindowSize() ); awt::Size aSize( getPreferredPlayerWindowSize() );
if( mbFakeVideo )
preparePlaybin( maURL, NULL );
DBG( "Player::createPlayerWindow %d %d length: %d", aSize.Width, aSize.Height, rArguments.getLength() ); DBG( "Player::createPlayerWindow %d %d length: %d", aSize.Width, aSize.Height, rArguments.getLength() );
if( aSize.Width > 0 && aSize.Height > 0 ) if( aSize.Width > 0 && aSize.Height > 0 )
...@@ -637,9 +685,15 @@ uno::Reference< ::media::XPlayerWindow > SAL_CALL Player::createPlayerWindow( co ...@@ -637,9 +685,15 @@ uno::Reference< ::media::XPlayerWindow > SAL_CALL Player::createPlayerWindow( co
uno::Reference< media::XFrameGrabber > SAL_CALL Player::createFrameGrabber() uno::Reference< media::XFrameGrabber > SAL_CALL Player::createFrameGrabber()
throw (uno::RuntimeException) 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;
} }
// ------------------------------------------------------------------------------ // ------------------------------------------------------------------------------
......
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
#include "gstcommon.hxx" #include "gstcommon.hxx"
#include "com/sun/star/media/XPlayer.hpp" #include "com/sun/star/media/XPlayer.hpp"
#include <cppuhelper/compbase2.hxx>
#include <cppuhelper/basemutex.hxx>
typedef struct _GstVideoOverlay GstVideoOverlay; typedef struct _GstVideoOverlay GstVideoOverlay;
...@@ -33,18 +35,21 @@ namespace avmedia { namespace gstreamer { ...@@ -33,18 +35,21 @@ namespace avmedia { namespace gstreamer {
// - Player - // - Player -
// ---------- // ----------
class Player : public ::cppu::WeakImplHelper2< ::com::sun::star::media::XPlayer, typedef ::cppu::WeakComponentImplHelper2< ::com::sun::star::media::XPlayer,
::com::sun::star::lang::XServiceInfo > ::com::sun::star::lang::XServiceInfo > GstPlayer_BASE;
class Player : public ::cppu::BaseMutex,
public GstPlayer_BASE
{ {
public: public:
Player( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxMgr ); Player( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxMgr );
~Player(); ~Player();
void preparePlaybin( const OUString& rURL, bool bFakeVideo ); void preparePlaybin( const OUString& rURL, GstElement *pSink );
bool create( const OUString& rURL ); bool create( const OUString& rURL );
void processMessage( GstMessage *message ); virtual void processMessage( GstMessage *message );
GstBusSyncReply processSyncMessage( GstMessage *message ); virtual GstBusSyncReply processSyncMessage( GstMessage *message );
// XPlayer // XPlayer
virtual void SAL_CALL start( ) throw (::com::sun::star::uno::RuntimeException); virtual void SAL_CALL start( ) throw (::com::sun::star::uno::RuntimeException);
...@@ -69,8 +74,10 @@ public: ...@@ -69,8 +74,10 @@ public:
virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) 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 ::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; ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxMgr;
OUString maURL; OUString maURL;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment