xref: /trunk/main/avmedia/source/win/framegrabber.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include <tools/prewin.h>
29 #if defined _MSC_VER
30 #pragma warning(push, 1)
31 #pragma warning(disable: 4917)
32 #endif
33 #include <windows.h>
34 #include <objbase.h>
35 #include <strmif.h>
36 #include <Amvideo.h>
37 #if defined(_MSC_VER) && (_MSC_VER < 1500)
38 #include <Qedit.h>
39 #else
40 #include "interface.hxx"
41 #endif
42 #include <uuids.h>
43 #if defined _MSC_VER
44 #pragma warning(pop)
45 #endif
46 #include <tools/postwin.h>
47 
48 #include "framegrabber.hxx"
49 #include "player.hxx"
50 
51 #include <tools/stream.hxx>
52 #include <vcl/graph.hxx>
53 #include <unotools/localfilehelper.hxx>
54 
55 #define AVMEDIA_WIN_FRAMEGRABBER_IMPLEMENTATIONNAME "com.sun.star.comp.avmedia.FrameGrabber_DirectX"
56 #define AVMEDIA_WIN_FRAMEGRABBER_SERVICENAME "com.sun.star.media.FrameGrabber_DirectX"
57 
58 using namespace ::com::sun::star;
59 
60 namespace avmedia { namespace win {
61 
62 // ----------------
63 // - FrameGrabber -
64 // ----------------
65 
66 FrameGrabber::FrameGrabber( const uno::Reference< lang::XMultiServiceFactory >& rxMgr ) :
67     mxMgr( rxMgr )
68 {
69     ::CoInitialize( NULL );
70 }
71 
72 // ------------------------------------------------------------------------------
73 
74 FrameGrabber::~FrameGrabber()
75 {
76     ::CoUninitialize();
77 }
78 
79 // ------------------------------------------------------------------------------
80 
81 IMediaDet* FrameGrabber::implCreateMediaDet( const ::rtl::OUString& rURL ) const
82 {
83     IMediaDet* pDet = NULL;
84 
85     if( SUCCEEDED( CoCreateInstance( CLSID_MediaDet, NULL, CLSCTX_INPROC_SERVER, IID_IMediaDet, (void**) &pDet ) ) )
86     {
87 		String aLocalStr;
88 
89 		if( ::utl::LocalFileHelper::ConvertURLToPhysicalName( rURL, aLocalStr ) && aLocalStr.Len() )
90 		{
91             if( !SUCCEEDED( pDet->put_Filename( ::SysAllocString( reinterpret_cast<LPCOLESTR>(aLocalStr.GetBuffer()) ) ) ) )
92             {
93                 pDet->Release();
94                 pDet = NULL;
95             }
96         }
97     }
98 
99     return pDet;
100 }
101 
102 // ------------------------------------------------------------------------------
103 
104 bool FrameGrabber::create( const ::rtl::OUString& rURL )
105 {
106     // just check if a MediaDet interface can be created with the given URL
107     IMediaDet*  pDet = implCreateMediaDet( rURL );
108 
109     if( pDet )
110     {
111         maURL = rURL;
112         pDet->Release();
113         pDet = NULL;
114     }
115     else
116         maURL = ::rtl::OUString();
117 
118     return( maURL.getLength() > 0 );
119 }
120 
121 // ------------------------------------------------------------------------------
122 
123 uno::Reference< graphic::XGraphic > SAL_CALL FrameGrabber::grabFrame( double fMediaTime )
124     throw (uno::RuntimeException)
125 {
126     uno::Reference< graphic::XGraphic > xRet;
127     IMediaDet*                          pDet = implCreateMediaDet( maURL );
128 
129     if( pDet )
130     {
131         double  fLength;
132         long    nStreamCount;
133         bool    bFound = false;
134 
135         if( SUCCEEDED( pDet->get_OutputStreams( &nStreamCount ) ) )
136         {
137             for( long n = 0; ( n < nStreamCount ) && !bFound; ++n )
138             {
139                 GUID aMajorType;
140 
141                 if( SUCCEEDED( pDet->put_CurrentStream( n ) )  &&
142                     SUCCEEDED( pDet->get_StreamType( &aMajorType ) ) &&
143                     ( aMajorType == MEDIATYPE_Video ) )
144                 {
145                     bFound = true;
146                 }
147             }
148         }
149 
150         if( bFound &&
151             ( S_OK == pDet->get_StreamLength( &fLength ) ) &&
152             ( fLength > 0.0 ) && ( fMediaTime >= 0.0 ) && ( fMediaTime <= fLength ) )
153         {
154             AM_MEDIA_TYPE   aMediaType;
155             long            nWidth = 0, nHeight = 0, nSize = 0;
156 
157             if( SUCCEEDED( pDet->get_StreamMediaType( &aMediaType ) ) )
158             {
159                 if( ( aMediaType.formattype == FORMAT_VideoInfo ) &&
160                     ( aMediaType.cbFormat >= sizeof( VIDEOINFOHEADER ) ) )
161                 {
162                     VIDEOINFOHEADER* pVih = reinterpret_cast< VIDEOINFOHEADER* >( aMediaType.pbFormat );
163 
164                     nWidth = pVih->bmiHeader.biWidth;
165                     nHeight = pVih->bmiHeader.biHeight;
166 
167                     if( nHeight < 0 )
168                         nHeight *= -1;
169                 }
170 
171                 if( aMediaType.cbFormat != 0 )
172                 {
173                     ::CoTaskMemFree( (PVOID) aMediaType.pbFormat );
174                     aMediaType.cbFormat = 0;
175                     aMediaType.pbFormat = NULL;
176                 }
177 
178                 if( aMediaType.pUnk != NULL )
179                 {
180                     aMediaType.pUnk->Release();
181                     aMediaType.pUnk = NULL;
182                 }
183             }
184 
185             if( ( nWidth > 0 ) && ( nHeight > 0 ) &&
186                 SUCCEEDED( pDet->GetBitmapBits( 0, &nSize, NULL, nWidth, nHeight ) ) &&
187                 ( nSize > 0  ) )
188             {
189                 char* pBuffer = new char[ nSize ];
190 
191                 try
192                 {
193                     if( SUCCEEDED( pDet->GetBitmapBits( fMediaTime, NULL, pBuffer, nWidth, nHeight ) ) )
194                     {
195                         SvMemoryStream  aMemStm( pBuffer, nSize, STREAM_READ | STREAM_WRITE );
196                         Bitmap          aBmp;
197 
198                         if( aBmp.Read( aMemStm, false ) && !aBmp.IsEmpty() )
199                         {
200                             const Graphic aGraphic( aBmp );
201                             xRet = aGraphic.GetXGraphic();
202                         }
203                     }
204                 }
205                 catch( ... )
206                 {
207                 }
208 
209                 delete [] pBuffer;
210             }
211         }
212 
213         pDet->Release();
214     }
215 
216     return xRet;
217 }
218 
219 // ------------------------------------------------------------------------------
220 
221 ::rtl::OUString SAL_CALL FrameGrabber::getImplementationName(  )
222     throw (uno::RuntimeException)
223 {
224     return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( AVMEDIA_WIN_FRAMEGRABBER_IMPLEMENTATIONNAME ) );
225 }
226 
227 // ------------------------------------------------------------------------------
228 
229 sal_Bool SAL_CALL FrameGrabber::supportsService( const ::rtl::OUString& ServiceName )
230     throw (uno::RuntimeException)
231 {
232     return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( AVMEDIA_WIN_FRAMEGRABBER_SERVICENAME ) );
233 }
234 
235 // ------------------------------------------------------------------------------
236 
237 uno::Sequence< ::rtl::OUString > SAL_CALL FrameGrabber::getSupportedServiceNames(  )
238     throw (uno::RuntimeException)
239 {
240     uno::Sequence< ::rtl::OUString > aRet(1);
241     aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( AVMEDIA_WIN_FRAMEGRABBER_SERVICENAME ) );
242 
243     return aRet;
244 }
245 
246 } // namespace win
247 } // namespace avmedia
248