1 /*
2  *  MovieData.cpp
3  *  lala
4  *
5  *  Created by Stephan Huber on Wed Mar 10 2004.
6  *  Copyright (c) 2004 __MyCompanyName__. All rights reserved.
7  *
8  */
9 #include <osg/GL>
10 #include <osg/Endian>
11 #include <osg/Image>
12 #include <osgDB/FileNameUtils>
13 
14 #include "MovieData.h"
15 #include "QTUtils.h"
16 
17 
18 
19 
MovieData()20 MovieData::MovieData() : _pointer(NULL), _movie(NULL), _gw(NULL), _fError(false), _isLooping(false)
21 {
22 
23 }
24 
25 
~MovieData()26 MovieData::~MovieData()
27 {
28     if (_pointer) free(_pointer);
29     if (_gw) DisposeGWorld(_gw);
30 
31     if (_movie) {
32         DisposeMovie(_movie);
33     }
34 }
35 
36 
37 
38 
load(osg::Image * image,std::string afilename,double startTime)39 void MovieData::load(osg::Image* image, std::string afilename, double startTime)
40 {
41     bool isUrl( osgDB::containsServerAddress(afilename) );
42 
43     std::string filename = afilename;
44     if (!isUrl) {
45         if (!osgDB::isFileNameNativeStyle(filename))
46             filename = osgDB::convertFileNameToNativeStyle(filename);
47     }
48 
49     image->setFileName(filename);
50 
51 
52     QTNewMoviePropertyElement newMovieProperties[2];
53     CFStringRef movieLocation = CFStringCreateWithCString(NULL, filename.c_str(), kCFStringEncodingUTF8);
54     CFURLRef movieURL(NULL);
55     Boolean trueValue = true;
56 
57     newMovieProperties[0].propClass = kQTPropertyClass_DataLocation;
58     if (!isUrl)
59     {
60         #ifdef __APPLE__
61             newMovieProperties[0].propID = kQTDataLocationPropertyID_CFStringPosixPath;
62         #else
63             newMovieProperties[0].propID = kQTDataLocationPropertyID_CFStringWindowsPath;
64         #endif
65 
66         newMovieProperties[0].propValueSize = sizeof(CFStringRef);
67         newMovieProperties[0].propValueAddress = &movieLocation;
68     }
69     else
70     {
71         movieURL = CFURLCreateWithString(kCFAllocatorDefault, movieLocation, NULL);
72 
73         newMovieProperties[0].propID = kQTDataLocationPropertyID_CFURL;
74         newMovieProperties[0].propValueSize = sizeof(movieURL);
75         newMovieProperties[0].propValueAddress = (void*)&movieURL;
76     }
77 
78     // make movie active
79     newMovieProperties[1].propClass = kQTPropertyClass_NewMovieProperty;
80     newMovieProperties[1].propID = kQTNewMoviePropertyID_Active;
81     newMovieProperties[1].propValueSize = sizeof(trueValue);
82     newMovieProperties[1].propValueAddress = &trueValue;
83 
84     // Instantiate the Movie
85     OSStatus status = NewMovieFromProperties(2, newMovieProperties, 0, NULL, &_movie);
86     CFRelease(movieLocation);
87     if (movieURL) CFRelease(movieURL);
88 
89     if (status !=0) {
90         _fError = true;
91         OSG_FATAL << " MovieData :: NewMovieFromProperties failed with err " << status<< std::endl;
92         return;
93     }
94 
95 
96     Rect bounds;
97 
98 #ifdef __APPLE__
99     GetRegionBounds(GetMovieBoundsRgn(_movie), &bounds);
100 #else
101     bounds = (*GetMovieBoundsRgn(_movie))->rgnBBox;
102 #endif
103 
104     _checkMovieError("Can't get movie bounds\n");
105 
106     OffsetRect(&bounds, -bounds.left, -bounds.top);
107     SetMovieBox(_movie, &bounds);
108     _checkMovieError("Can't set movie box\n");
109 
110     _movieWidth = bounds.right;
111     _movieHeight = bounds.bottom;
112 
113     _timescale = GetMovieTimeScale(_movie);
114 
115     _initImage(image);
116     if (!_fError) _initGWorldStuff(image);
117 
118 
119     if (!_fError) {
120 
121         if ( startTime == 0.0)
122             GoToBeginningOfMovie(_movie);
123         else {
124             TimeValue t = (TimeValue) (startTime*_timescale);
125             SetMovieTimeValue(_movie,t);
126         }
127 
128         UpdateMovie(_movie);
129         SetMovieRate(_movie,0.0);
130         SetMovieActive(_movie, true);
131         UpdateMovie(_movie);
132         MoviesTask(_movie,0);
133     }
134 }
135 
136 
137 // ---------------------------------------------------------------------------
138 // _intImage
139 // create image for storing
140 // ---------------------------------------------------------------------------
141 
_initImage(osg::Image * image)142 void MovieData::_initImage(osg::Image* image)
143 {
144 
145     void* buffer;
146 
147 
148     _textureWidth = ((_movieWidth + 7) >> 3) << 3;
149     _textureHeight = _movieHeight;
150 
151     // some magic alignment...
152     _pointer = (char*)malloc(4 * _textureWidth * _textureHeight + 32);
153 
154     if (_pointer == NULL) {
155         OSG_FATAL << "MovieData: " << "Can't allocate texture buffer" << std::endl;
156         _fError= true;
157     }
158 
159     buffer = (void*)(((unsigned long)(_pointer + 31) >> 5) << 5);
160 
161     GLenum internalFormat = (osg::getCpuByteOrder()==osg::BigEndian)?
162                             GL_UNSIGNED_INT_8_8_8_8_REV :
163                             GL_UNSIGNED_INT_8_8_8_8;
164 
165     image->setImage(_textureWidth,_textureHeight,1,
166                    (GLint) GL_RGBA8,
167                    (GLenum)GL_BGRA,
168                    internalFormat,
169                    (unsigned char*) buffer,osg::Image::NO_DELETE,4);
170 
171 }
172 
173 // ---------------------------------------------------------------------------
174 // _initGWorldStuff
175 // init gworld-stuff, so quicktime can play the movie into the gWorld.
176 // ---------------------------------------------------------------------------
177 
_initGWorldStuff(osg::Image * image)178 void MovieData::_initGWorldStuff(osg::Image * image)  {
179 
180     Rect textureBounds;
181     OSStatus err;
182     GDHandle        origDevice;
183     CGrafPtr        origPort;
184     PixMapHandle pixmap = NULL;
185 
186     textureBounds.left = 0;
187     textureBounds.top = 0;
188     textureBounds.right = image->s();
189     textureBounds.bottom = image->t();
190     err = QTNewGWorldFromPtr(&_gw, k32ARGBPixelFormat, &textureBounds, NULL, NULL, 0, image->data(), 4 * image->s());
191 
192     if (err !=0 )
193     {
194         OSG_FATAL << "MovieData : Could not create gWorld" << std::endl;
195     }
196 
197     GetGWorld (&origPort, &origDevice);
198     SetGWorld(_gw, NULL);                                         // set current graphics port to offscreen
199     SetMovieGWorld(_movie, (CGrafPtr)_gw, NULL);
200 
201     _checkMovieError("SetMovieGWorld failed");
202 
203     pixmap = GetGWorldPixMap (_gw);
204     if (pixmap)
205     {
206         if (!LockPixels (pixmap))                                        // lock offscreen pixel map
207         {
208             OSG_FATAL << "Could not lock PixMap" << std::endl;
209             ExitToShell ();
210         }
211     }
212     else
213     {
214         OSG_FATAL << "Could not GetGWorldPixMap" << std::endl;
215         ExitToShell ();
216     }
217 
218     SetGWorld(origPort, origDevice);
219 
220 }
221 
setMovieTime(double atime)222 void MovieData::setMovieTime(double atime) {
223     double time = (atime > getMovieDuration()) ? getMovieDuration() : atime;
224 
225     TimeValue t = (TimeValue) (time * _timescale);
226     SetMovieTimeValue(_movie,t);
227     _checkMovieError("setMovieTime failed");
228     UpdateMovie(_movie);
229     MoviesTask(_movie,0);
230 
231 
232 }
233 
setMovieRate(double rate)234 void MovieData::setMovieRate(double rate) {
235     // OSG_ALWAYS << "new movierate: " << rate << " current: " << getMovieRate() << std::endl;
236     _movieRate = rate;
237     if ((rate != 0) && (_preRolled == false)) {
238         PrerollMovie(_movie, GetMovieTime(_movie,NULL), X2Fix(rate));
239         _checkMovieError("PrerollMovie failed");
240         _preRolled = true;
241     }
242 
243     SetMovieRate(_movie, X2Fix(rate));
244     _checkMovieError("setMovieRate failed");
245     MoviesTask(_movie, 0);
246     _checkMovieError("MoviesTask failed");
247 
248     UpdateMovie(_movie);
249     _checkMovieError("UpdateMovie failed");
250 
251 }
252 
253 
254 
255 
256