1*e8649ecdSHerbert Dürr /************************************************************** 2*e8649ecdSHerbert Dürr * 3*e8649ecdSHerbert Dürr * Licensed to the Apache Software Foundation (ASF) under one 4*e8649ecdSHerbert Dürr * or more contributor license agreements. See the NOTICE file 5*e8649ecdSHerbert Dürr * distributed with this work for additional information 6*e8649ecdSHerbert Dürr * regarding copyright ownership. The ASF licenses this file 7*e8649ecdSHerbert Dürr * to you under the Apache License, Version 2.0 (the 8*e8649ecdSHerbert Dürr * "License"); you may not use this file except in compliance 9*e8649ecdSHerbert Dürr * with the License. You may obtain a copy of the License at 10*e8649ecdSHerbert Dürr * 11*e8649ecdSHerbert Dürr * http://www.apache.org/licenses/LICENSE-2.0 12*e8649ecdSHerbert Dürr * 13*e8649ecdSHerbert Dürr * Unless required by applicable law or agreed to in writing, 14*e8649ecdSHerbert Dürr * software distributed under the License is distributed on an 15*e8649ecdSHerbert Dürr * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*e8649ecdSHerbert Dürr * KIND, either express or implied. See the License for the 17*e8649ecdSHerbert Dürr * specific language governing permissions and limitations 18*e8649ecdSHerbert Dürr * under the License. 19*e8649ecdSHerbert Dürr * 20*e8649ecdSHerbert Dürr *************************************************************/ 21*e8649ecdSHerbert Dürr 22*e8649ecdSHerbert Dürr #include "macavf_framegrabber.hxx" 23*e8649ecdSHerbert Dürr #include "macavf_player.hxx" 24*e8649ecdSHerbert Dürr 25*e8649ecdSHerbert Dürr #include <tools/stream.hxx> 26*e8649ecdSHerbert Dürr #include <vcl/graph.hxx> 27*e8649ecdSHerbert Dürr #include <vcl/cvtgrf.hxx> 28*e8649ecdSHerbert Dürr #include <unotools/localfilehelper.hxx> 29*e8649ecdSHerbert Dürr 30*e8649ecdSHerbert Dürr using namespace ::com::sun::star; 31*e8649ecdSHerbert Dürr 32*e8649ecdSHerbert Dürr namespace avmedia { namespace macavf { 33*e8649ecdSHerbert Dürr 34*e8649ecdSHerbert Dürr // ---------------- 35*e8649ecdSHerbert Dürr // - FrameGrabber - 36*e8649ecdSHerbert Dürr // ---------------- 37*e8649ecdSHerbert Dürr 38*e8649ecdSHerbert Dürr FrameGrabber::FrameGrabber( const uno::Reference< lang::XMultiServiceFactory >& /*rxMgr*/ ) 39*e8649ecdSHerbert Dürr : mpImageGen( NULL ) 40*e8649ecdSHerbert Dürr {} 41*e8649ecdSHerbert Dürr 42*e8649ecdSHerbert Dürr // ------------------------------------------------------------------------------ 43*e8649ecdSHerbert Dürr 44*e8649ecdSHerbert Dürr FrameGrabber::~FrameGrabber() 45*e8649ecdSHerbert Dürr { 46*e8649ecdSHerbert Dürr if( mpImageGen ) 47*e8649ecdSHerbert Dürr CFRelease( mpImageGen ); 48*e8649ecdSHerbert Dürr } 49*e8649ecdSHerbert Dürr 50*e8649ecdSHerbert Dürr // ------------------------------------------------------------------------------ 51*e8649ecdSHerbert Dürr 52*e8649ecdSHerbert Dürr bool FrameGrabber::create( const ::rtl::OUString& rURL ) 53*e8649ecdSHerbert Dürr { 54*e8649ecdSHerbert Dürr // TODO: use AVPlayer's movie directly instead of loading it here? 55*e8649ecdSHerbert Dürr 56*e8649ecdSHerbert Dürr NSString* pNSStr = [NSString stringWithCharacters:rURL.getStr() length:rURL.getLength()]; 57*e8649ecdSHerbert Dürr NSURL* pNSURL = [NSURL URLWithString: [pNSStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; 58*e8649ecdSHerbert Dürr AVAsset* pMovie = [AVURLAsset URLAssetWithURL:pNSURL options:nil]; 59*e8649ecdSHerbert Dürr if( !pMovie ) 60*e8649ecdSHerbert Dürr { 61*e8649ecdSHerbert Dürr OSL_TRACE( "AVGrabber::create() cannot load url=\"%s\"", [pNSStr UTF8String] ); 62*e8649ecdSHerbert Dürr return false; 63*e8649ecdSHerbert Dürr } 64*e8649ecdSHerbert Dürr if( [[pMovie tracksWithMediaType:AVMediaTypeVideo] count] == 0) 65*e8649ecdSHerbert Dürr { 66*e8649ecdSHerbert Dürr OSL_TRACE( "AVGrabber::create() found no video in url=\"%s\"", [pNSStr UTF8String] ); 67*e8649ecdSHerbert Dürr return false; 68*e8649ecdSHerbert Dürr } 69*e8649ecdSHerbert Dürr 70*e8649ecdSHerbert Dürr mpImageGen = [AVAssetImageGenerator assetImageGeneratorWithAsset:pMovie]; 71*e8649ecdSHerbert Dürr CFRetain( mpImageGen ); 72*e8649ecdSHerbert Dürr return true; 73*e8649ecdSHerbert Dürr } 74*e8649ecdSHerbert Dürr 75*e8649ecdSHerbert Dürr // ------------------------------------------------------------------------------ 76*e8649ecdSHerbert Dürr 77*e8649ecdSHerbert Dürr uno::Reference< graphic::XGraphic > SAL_CALL FrameGrabber::grabFrame( double fMediaTime ) 78*e8649ecdSHerbert Dürr throw (uno::RuntimeException) 79*e8649ecdSHerbert Dürr { 80*e8649ecdSHerbert Dürr uno::Reference< graphic::XGraphic > xRet; 81*e8649ecdSHerbert Dürr if( !mpImageGen ) 82*e8649ecdSHerbert Dürr return xRet; 83*e8649ecdSHerbert Dürr OSL_TRACE( "AVPlayer::grabFrame( %.3fsec)", fMediaTime ); 84*e8649ecdSHerbert Dürr 85*e8649ecdSHerbert Dürr // get the requested image from the movie 86*e8649ecdSHerbert Dürr CGImage* pCGImage = [mpImageGen copyCGImageAtTime:CMTimeMakeWithSeconds(fMediaTime,1000) actualTime:NULL error:NULL]; 87*e8649ecdSHerbert Dürr 88*e8649ecdSHerbert Dürr // convert the image to a TIFF-formatted byte-array 89*e8649ecdSHerbert Dürr CFMutableDataRef pCFData = CFDataCreateMutable( kCFAllocatorDefault, 0 ); 90*e8649ecdSHerbert Dürr CGImageDestination* pCGImgDest = CGImageDestinationCreateWithData( pCFData, kUTTypeTIFF, 1, 0 ); 91*e8649ecdSHerbert Dürr CGImageDestinationAddImage( pCGImgDest, pCGImage, NULL ); 92*e8649ecdSHerbert Dürr CGImageDestinationFinalize( pCGImgDest ); 93*e8649ecdSHerbert Dürr CFRelease( pCGImgDest ); 94*e8649ecdSHerbert Dürr const long nBitmapLen = CFDataGetLength( pCFData ); 95*e8649ecdSHerbert Dürr void* pBitmapBytes = (void*)CFDataGetBytePtr( pCFData ); 96*e8649ecdSHerbert Dürr 97*e8649ecdSHerbert Dürr // convert the image into the return-value type which is a graphic::XGraphic 98*e8649ecdSHerbert Dürr SvMemoryStream aMemStm( pBitmapBytes, nBitmapLen, STREAM_READ | STREAM_WRITE ); 99*e8649ecdSHerbert Dürr Graphic aGraphic; 100*e8649ecdSHerbert Dürr if( GraphicConverter::Import( aMemStm, aGraphic, CVT_TIF ) == ERRCODE_NONE ) 101*e8649ecdSHerbert Dürr xRet = aGraphic.GetXGraphic(); 102*e8649ecdSHerbert Dürr 103*e8649ecdSHerbert Dürr // clean up resources 104*e8649ecdSHerbert Dürr CFRelease( pCFData ); 105*e8649ecdSHerbert Dürr return xRet; 106*e8649ecdSHerbert Dürr } 107*e8649ecdSHerbert Dürr 108*e8649ecdSHerbert Dürr // ------------------------------------------------------------------------------ 109*e8649ecdSHerbert Dürr 110*e8649ecdSHerbert Dürr ::rtl::OUString SAL_CALL FrameGrabber::getImplementationName( ) 111*e8649ecdSHerbert Dürr throw (uno::RuntimeException) 112*e8649ecdSHerbert Dürr { 113*e8649ecdSHerbert Dürr return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( AVMEDIA_MACAVF_FRAMEGRABBER_IMPLEMENTATIONNAME ) ); 114*e8649ecdSHerbert Dürr } 115*e8649ecdSHerbert Dürr 116*e8649ecdSHerbert Dürr // ------------------------------------------------------------------------------ 117*e8649ecdSHerbert Dürr 118*e8649ecdSHerbert Dürr sal_Bool SAL_CALL FrameGrabber::supportsService( const ::rtl::OUString& ServiceName ) 119*e8649ecdSHerbert Dürr throw (uno::RuntimeException) 120*e8649ecdSHerbert Dürr { 121*e8649ecdSHerbert Dürr return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( AVMEDIA_MACAVF_FRAMEGRABBER_SERVICENAME ) ); 122*e8649ecdSHerbert Dürr } 123*e8649ecdSHerbert Dürr 124*e8649ecdSHerbert Dürr // ------------------------------------------------------------------------------ 125*e8649ecdSHerbert Dürr 126*e8649ecdSHerbert Dürr uno::Sequence< ::rtl::OUString > SAL_CALL FrameGrabber::getSupportedServiceNames( ) 127*e8649ecdSHerbert Dürr throw (uno::RuntimeException) 128*e8649ecdSHerbert Dürr { 129*e8649ecdSHerbert Dürr uno::Sequence< ::rtl::OUString > aRet(1); 130*e8649ecdSHerbert Dürr aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( AVMEDIA_MACAVF_FRAMEGRABBER_SERVICENAME ) ); 131*e8649ecdSHerbert Dürr 132*e8649ecdSHerbert Dürr return aRet; 133*e8649ecdSHerbert Dürr } 134*e8649ecdSHerbert Dürr 135*e8649ecdSHerbert Dürr } // namespace macavf 136*e8649ecdSHerbert Dürr } // namespace avmedia 137*e8649ecdSHerbert Dürr 138