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