11218
|
1 /*
|
|
2 File: QTUtilities.c
|
|
3
|
|
4 Description: Miscellaneous QuickTime utility routines.
|
|
5
|
|
6 Copyright: © Copyright 2003 Apple Computer, Inc. All rights reserved.
|
|
7
|
|
8 Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
|
|
9 ("Apple") in consideration of your agreement to the following terms, and your
|
|
10 use, installation, modification or redistribution of this Apple software
|
|
11 constitutes acceptance of these terms. If you do not agree with these terms,
|
|
12 please do not use, install, modify or redistribute this Apple software.
|
|
13
|
|
14 In consideration of your agreement to abide by the following terms, and subject
|
|
15 to these terms, Apple grants you a personal, non-exclusive license, under Apple’s
|
|
16 copyrights in this original Apple software (the "Apple Software"), to use,
|
|
17 reproduce, modify and redistribute the Apple Software, with or without
|
|
18 modifications, in source and/or binary forms; provided that if you redistribute
|
|
19 the Apple Software in its entirety and without modifications, you must retain
|
|
20 this notice and the following text and disclaimers in all such redistributions of
|
|
21 the Apple Software. Neither the name, trademarks, service marks or logos of
|
|
22 Apple Computer, Inc. may be used to endorse or promote products derived from the
|
|
23 Apple Software without specific prior written permission from Apple. Except as
|
|
24 expressly stated in this notice, no other rights or licenses, express or implied,
|
|
25 are granted by Apple herein, including but not limited to any patent rights that
|
|
26 may be infringed by your derivative works or by other works in which the Apple
|
|
27 Software may be incorporated.
|
|
28
|
|
29 The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
|
|
30 WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
|
|
31 WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
32 PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
|
|
33 COMBINATION WITH YOUR PRODUCTS.
|
|
34
|
|
35 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
|
|
36 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
37 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
38 ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
|
|
39 OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
|
|
40 (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
|
|
41 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
42
|
|
43 Change History (most recent first):
|
|
44
|
|
45 */
|
|
46
|
|
47 #include "QTUtilities.h"
|
|
48 #include "Utilities.h"
|
|
49
|
|
50 #define BailErr(x) {if (x != noErr) goto bail;}
|
|
51
|
|
52 //////////
|
|
53 //
|
|
54 // GetMovieFromFile
|
|
55 // Opens a movie file, then creates a new movie for the file
|
|
56 //
|
|
57 //////////
|
|
58
|
|
59 OSErr GetMovieFromFile(FSSpec *fsspecPtr, Movie *theMovie)
|
|
60 {
|
|
61 short resRefNum = -1;
|
|
62 OSErr result;
|
|
63
|
|
64 *theMovie = NULL;
|
|
65
|
|
66 result = OpenMovieFile(fsspecPtr, &resRefNum, 0);
|
|
67 if (result == noErr)
|
|
68 {
|
|
69 short actualResId = DoTheRightThing;
|
|
70
|
|
71 result = NewMovieFromFile(theMovie,
|
|
72 resRefNum,
|
|
73 &actualResId,
|
|
74 (unsigned char *) 0,
|
|
75 0,
|
|
76 (Boolean *) 0);
|
|
77 CloseMovieFile(resRefNum);
|
|
78 }
|
|
79
|
|
80 return result;
|
|
81 }
|
|
82
|
|
83 //////////
|
|
84 //
|
|
85 // GetAMovieFile
|
|
86 // Prompt the user for a movie file, then open
|
|
87 // the file and create a movie for it.
|
|
88 //
|
|
89 //////////
|
|
90
|
|
91 OSErr GetAMovieFile(Movie *theMovie)
|
|
92 {
|
|
93 OSType myTypeList[2] = {kQTFileTypeMovie, kQTFileTypeQuickTimeImage};
|
|
94 FSSpec theFSSpec;
|
|
95 OSErr result = noErr;
|
|
96
|
|
97 *theMovie = nil;
|
|
98
|
|
99 result = GetOneFileWithPreview(2, myTypeList, &theFSSpec, NULL);
|
|
100 if (result != userCanceledErr)
|
|
101 {
|
|
102 result = GetMovieFromFile(&theFSSpec, theMovie);
|
|
103 }
|
|
104
|
|
105 return result;
|
|
106 }
|
|
107
|
|
108 //////////
|
|
109 //
|
|
110 // NormalizeMovieRect
|
|
111 //
|
|
112 //////////
|
|
113
|
|
114 void NormalizeMovieRect(Movie theMovie)
|
|
115 {
|
|
116 Rect movieBounds;
|
|
117
|
|
118 GetMovieBox(theMovie, &movieBounds);
|
|
119 OffsetRect(&movieBounds, -movieBounds.left, -movieBounds.top);
|
|
120 movieBounds.right = movieBounds.left + 640;
|
|
121 movieBounds.bottom = movieBounds.top + 480;
|
|
122 SetMovieBox(theMovie, &movieBounds);
|
|
123 }
|
|
124
|
|
125 //////////
|
|
126 //
|
|
127 // EraseRectAndAlpha
|
|
128 // Zeros out a section of the GWorld, including alpha.
|
|
129 //
|
|
130 //////////
|
|
131
|
|
132 void EraseRectAndAlpha(GWorldPtr gWorld, Rect *pRect)
|
|
133 {
|
|
134 PixMapHandle pixMap = GetGWorldPixMap(gWorld);
|
|
135 long rows;
|
|
136 Ptr rowBaseAddr;
|
|
137
|
|
138
|
|
139 LockPixels(pixMap);
|
|
140 rows = pRect->bottom - pRect->top;
|
|
141
|
|
142 rowBaseAddr = GetPixBaseAddr(pixMap) + (GetPixRowBytes(pixMap) & 0x3fff) * pRect->top + pRect->left * GetPixDepth(pixMap) / 8;
|
|
143 do
|
|
144 {
|
|
145 long cols;
|
|
146 UInt32 *baseAddr;
|
|
147
|
|
148 cols = pRect->right - pRect->left;
|
|
149 baseAddr = (UInt32*)rowBaseAddr;
|
|
150 rowBaseAddr += (**pixMap).rowBytes & 0x3fff;
|
|
151 do
|
|
152 {
|
|
153 *baseAddr++ = 0;
|
|
154 } while (--cols);
|
|
155 } while (--rows);
|
|
156
|
|
157 UnlockPixels(pixMap);
|
|
158
|
|
159 } // EraseRectAndAlpha
|
|
160
|
|
161 //////////
|
|
162 //
|
|
163 // CreateDecompSeqForSGChannelData
|
|
164 // Create a decompression sequence for the passed
|
|
165 // Sequence Grabber channel data
|
|
166 //
|
|
167 //////////
|
|
168
|
|
169 OSErr CreateDecompSeqForSGChannelData(SGChannel sgChannel, Rect *srcBounds, GWorldPtr imageDestination, ImageSequence *imageSeqID)
|
|
170 {
|
|
171 OSErr err = noErr;
|
|
172
|
|
173 ImageDescriptionHandle imageDesc = (ImageDescriptionHandle)NewHandle(sizeof(ImageDescription));
|
|
174 if (imageDesc)
|
|
175 {
|
|
176
|
|
177 err = SGGetChannelSampleDescription(sgChannel,(Handle)imageDesc);
|
|
178 // The original version of this code had a bug - it passed in a Crop Rect to DecompressSequenceBegin instead of a scaling matrix
|
|
179 // This only worked because of another bug inside QT that reated the crop Rect as a destination rect for DV
|
|
180 // the following code does the right thing in all cases.
|
|
181
|
|
182 if (err == noErr)
|
|
183 {
|
|
184 MatrixRecord mr;
|
|
185 Rect fromR;
|
|
186
|
|
187 fromR.left = 0;
|
|
188 fromR.top = 0;
|
|
189 fromR.right = (**imageDesc).width;
|
|
190 fromR.bottom = (**imageDesc).height;
|
|
191 RectMatrix(&mr, &fromR, srcBounds);
|
|
192
|
|
193 err = DecompressSequenceBegin(imageSeqID, imageDesc, imageDestination, 0, nil, &mr,srcCopy,nil,0, codecNormalQuality, bestSpeedCodec);
|
|
194 }
|
|
195
|
|
196 DisposeHandle((Handle)imageDesc);
|
|
197 }
|
|
198 else
|
|
199 {
|
|
200 err = MemError();
|
|
201 }
|
|
202
|
|
203 return err;
|
|
204 }
|
|
205
|
|
206
|
|
207 //////////
|
|
208 //
|
|
209 // CreateDecompSeqForGWorldData
|
|
210 // Create a decompression sequence for the specified gworld data
|
|
211 //
|
|
212 //////////
|
|
213
|
|
214 OSErr CreateDecompSeqForGWorldData(GWorldPtr srcGWorld, Rect *srcBounds, MatrixRecordPtr mr, GWorldPtr imageDestination, ImageSequence *imageSeqID)
|
|
215 {
|
|
216 OSErr err;
|
|
217
|
|
218 ImageDescriptionHandle imageDesc = (ImageDescriptionHandle)NewHandle(sizeof(ImageDescription));
|
|
219 if (imageDesc)
|
|
220 {
|
|
221 err = MakeImageDescriptionForPixMap (GetGWorldPixMap(srcGWorld), &imageDesc);
|
|
222 err = DecompressSequenceBegin( imageSeqID,
|
|
223 imageDesc,
|
|
224 imageDestination,
|
|
225 0,
|
|
226 srcBounds,
|
|
227 mr,
|
|
228 srcCopy,
|
|
229 nil,
|
|
230 0,
|
|
231 codecNormalQuality,
|
|
232 bestSpeedCodec);
|
|
233 DisposeHandle((Handle)imageDesc);
|
|
234 }
|
|
235 else
|
|
236 {
|
|
237 err = MemError();
|
|
238 }
|
|
239
|
|
240 return err;
|
|
241 }
|
|
242
|
|
243 //////////
|
|
244 //
|
|
245 // CreateNewSGChannelForRecording
|
|
246 // - create a new Sequence Grabber video channel
|
|
247 // - let the use configure the channel
|
|
248 // - set the channel bounds, usage
|
|
249 // - set a data proc for the channel
|
|
250 // - start recording data
|
|
251 //
|
|
252 //////////
|
|
253
|
|
254 OSErr CreateNewSGChannelForRecording(ComponentInstance seqGrab, SGDataUPP dataProc, CGrafPtr drawPort, Rect *theRect, SGChannel *sgChannel, long refCon)
|
|
255 {
|
|
256 OSErr err = noErr;
|
|
257
|
|
258 BailErr((err = SGInitialize(seqGrab)));
|
|
259
|
|
260 // tell it we're not making a movie
|
|
261 BailErr((err = SGSetDataRef(seqGrab,0,0,seqGrabDontMakeMovie)));
|
|
262 // It wants a port, even if its not drawing to it
|
|
263 BailErr((err = SGSetGWorld(seqGrab, drawPort, GetMainDevice())));
|
|
264 BailErr((err = SGNewChannel(seqGrab, VideoMediaType, sgChannel)));
|
|
265
|
|
266 // let the user configure the video channel
|
|
267 //BailErr((err = SGSettingsDialog(seqGrab, *sgChannel, 0, nil, 0, nil, 0))); // ************************
|
|
268 // ************************************************************
|
|
269
|
|
270
|
|
271
|
|
272 BailErr((err = SGSetChannelBounds(*sgChannel, theRect)));
|
|
273 // set usage for new video channel to avoid playthrough
|
|
274 BailErr((err = SGSetChannelUsage(*sgChannel, seqGrabRecord ))); //note we don't set seqGrabPlayDuringRecord
|
|
275 BailErr((err = SGSetDataProc(seqGrab, dataProc, refCon)));
|
|
276 BailErr((err = SGStartRecord(seqGrab)));
|
|
277
|
|
278 bail:
|
|
279 return err;
|
|
280 }
|
|
281
|
|
282 //////////
|
|
283 //
|
|
284 // DoCloseSG
|
|
285 // Terminate recording for our SG channel - dispose of the channel and
|
|
286 // the associated SG component instance
|
|
287 //
|
|
288 //////////
|
|
289
|
|
290 void DoCloseSG(ComponentInstance seqGrab, SGChannel sgChannel, SGDataUPP dataProc)
|
|
291 {
|
|
292 if(seqGrab)
|
|
293 {
|
|
294 SGStop(seqGrab);
|
|
295 SGSetDataProc(seqGrab, NULL ,NULL);
|
|
296 if (dataProc)
|
|
297 {
|
|
298 DisposeSGDataUPP(dataProc);
|
|
299 }
|
|
300
|
|
301 SGDisposeChannel(seqGrab, sgChannel);
|
|
302 CloseComponent(seqGrab);
|
|
303 }
|
|
304 }
|
|
305
|
|
306
|