IVT
QuicktimeCapture.cpp
Go to the documentation of this file.
1 // ****************************************************************************
2 // This file is part of the Integrating Vision Toolkit (IVT).
3 //
4 // The IVT is maintained by the Karlsruhe Institute of Technology (KIT)
5 // (www.kit.edu) in cooperation with the company Keyetech (www.keyetech.de).
6 //
7 // Copyright (C) 2014 Karlsruhe Institute of Technology (KIT).
8 // All rights reserved.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are met:
12 //
13 // 1. Redistributions of source code must retain the above copyright
14 // notice, this list of conditions and the following disclaimer.
15 //
16 // 2. Redistributions in binary form must reproduce the above copyright
17 // notice, this list of conditions and the following disclaimer in the
18 // documentation and/or other materials provided with the distribution.
19 //
20 // 3. Neither the name of the KIT nor the names of its contributors may be
21 // used to endorse or promote products derived from this software
22 // without specific prior written permission.
23 //
24 // THIS SOFTWARE IS PROVIDED BY THE KIT AND CONTRIBUTORS “AS IS” AND ANY
25 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 // DISCLAIMED. IN NO EVENT SHALL THE KIT OR CONTRIBUTORS BE LIABLE FOR ANY
28 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 // ****************************************************************************
35 // ****************************************************************************
36 // Filename: QuicktimeCapture.cpp
37 // Author: Pedram Azad
38 // Date: 2005
39 // ****************************************************************************
40 
41 
42 // ****************************************************************************
43 // Includes
44 // ****************************************************************************
45 
46 #include "QuicktimeCapture.h"
47 #include "Image/ByteImage.h"
48 
49 #include <QuickTime/QuickTimeStreaming.h>
50 
51 
52 
53 // ****************************************************************************
54 // Constructor / Destructor
55 // ****************************************************************************
56 
57 CQuicktimeCapture::CQuicktimeCapture(VideoMode mode, const char *pComponentName) : m_mode(mode)
58 {
59  grabber = 0;
60  videoChannel = 0;
61  gWorld = 0;
62  m_pBuffer = 0;
63  imgDesc = 0;
64 
65  width = -1;
66  height = -1;
67 
68  m_sComponentName = "";
69 
70  if (pComponentName)
71  m_sComponentName += pComponentName;
72 
73  m_bImagePending = false;
74 }
75 
77 {
78  CloseCamera();
79 }
80 
81 
82 // ****************************************************************************
83 // Methods
84 // ****************************************************************************
85 
87 {
88  CloseCamera();
89 
90  switch (m_mode)
91  {
92  case e320x240:
93  width = 320;
94  height = 240;
95  break;
96 
97  case e640x480:
98  width = 640;
99  height = 480;
100  break;
101 
102  default:
103  return false;
104  }
105 
106  srcRect.left = 0;
107  srcRect.right = width - 1;
108  srcRect.top = 0;
109  srcRect.bottom = height - 1;
110 
111  Component comp = 0;
112  Handle grabberName = NewHandle(0);
113  Handle info = NewHandle(0);
114  ComponentDescription desc;
115 
116  desc.componentType = SeqGrabComponentType;
117  desc.componentSubType = 0;
118  desc.componentManufacturer = 0;
119  desc.componentFlags = 0;
120  desc.componentFlagsMask = 0;
121 
122  // find a sequence grabber that matches the given component name
123  bool bFound = false;
124  while (comp = FindNextComponent(comp, &desc))
125  {
126  if (GetComponentInfo(comp, &desc, grabberName, info, 0) != noErr)
127  {
128  printf("error: could not get info on component id = %i\n", comp);
129  return false;
130  }
131 
132  printf("grabber: '%s'\n", *grabberName + 1);
133 
134  if (m_sComponentName.length() == 0 || strcmp(m_sComponentName.c_str(), *grabberName + 1) == 0)
135  {
136  bFound = true;
137  break;
138  }
139  }
140 
141  if (!bFound)
142  {
143  printf("error: could not find a sequence grabber named '%s'\n", m_sComponentName.c_str());
144  return false;
145  }
146 
147  // found grabber, open and initialize it
148  grabber = OpenComponent(comp);
149 
150  if (!grabber)
151  {
152  printf("error: could not open sequence grabber\n");
153  return false;
154  }
155 
156  if (SGInitialize(grabber) != noErr)
157  {
158  printf("errror: could not initialize the sequence grabber\n");
159  return false;
160  }
161 
162  if (SGSetDataRef(grabber, 0, 0, seqGrabDontMakeMovie) != noErr)
163  {
164  printf("error: could not set data reference on sequence grabber\n");
165  return false;
166  }
167 
168  if (QTNewGWorld(&gWorld, k24RGBPixelFormat, &srcRect, 0, 0, 0) != noErr)
169  {
170  printf("error: could not create new gworld\n");
171  return false;
172  }
173 
174  if (!LockPixels(GetPortPixMap(gWorld)))
175  {
176  printf("error: could not lock pixels in new gworld\n");
177  return false;
178  }
179 
180  if (SGSetGWorld(grabber, gWorld, 0) != noErr)
181  {
182  printf("error: could not set gworld\n");
183  return false;
184  }
185 
186  // create video channel
187  if (SGNewChannel(grabber, VideoMediaType, &videoChannel) != noErr || !videoChannel)
188  {
189  printf("error: could not open video channel\n");
190  return false;
191  }
192 
193  if (SGSetChannelUsage(videoChannel, seqGrabRecord) != noErr)
194  {
195  printf("error: could not set channel usage to 'record'\n");
196  return false;
197  }
198 
199  if (SGSetChannelBounds(videoChannel, &srcRect) != noErr)
200  {
201  printf("error: could not set channel bounds to %ix%i\n", width, height);
202  return false;
203  }
204 
205  if (SGSetDataProc(grabber, NewSGDataUPP(sDataProc), (long)this) != noErr)
206  {
207  printf("error: could not set data proc\n");
208  return false;
209  }
210 
211  SGStartRecord(grabber);
212 
213  return true;
214 }
215 
217 {
218  if (grabber)
219  {
220  SGStop(grabber);
221 
222  if (videoChannel)
223  {
224  SGDisposeChannel(grabber, videoChannel);
225  videoChannel = 0;
226  }
227 
228  if (gWorld)
229  {
230  DisposeGWorld(gWorld);
231  gWorld = 0;
232  }
233 
234  grabber = 0;
235  }
236 
237  m_bImagePending = false;
238 }
239 
241 {
242  if (!videoChannel)
243  return false;
244 
245  CByteImage *pImage = ppImages[0];
246  if (pImage->width != width || pImage->height != height || pImage->type != CByteImage::eRGB24)
247  return false;
248 
249  while (!m_bImagePending)
250  SGIdle(grabber);
251 
252  ImageSequence image_sequence;
253 
254  if (DecompressSequenceBegin(&image_sequence, imgDesc, gWorld, 0, &srcRect, 0, srcCopy, 0, 0, codecNormalQuality, bestSpeedCodec) != noErr)
255  {
256  printf("error: could not begin decompression\n");
257  return false;
258  }
259 
260  CodecFlags ignore;
261 
262  DecompressSequenceFrameS(image_sequence, m_pBuffer, m_lImageLength, 0, &ignore, NULL);
263 
264  const int nBytes = 3 * pImage->width * pImage->height;
265  const unsigned char *input = (unsigned char *) GetPixBaseAddr(GetGWorldPixMap(gWorld));
266  unsigned char *output = pImage->pixels;
267  for (int i = 0, offset = 0; i < nBytes; i += 3, offset += 4)
268  {
269  output[i] = input[offset + 1];
270  output[i + 1] = input[offset + 2];
271  output[i + 2] = input[offset + 3];
272  }
273 
274  CDSequenceEnd(image_sequence);
275 
276  m_bImagePending = false;
277 
278  return true;
279 }
280 
281 pascal OSErr CQuicktimeCapture::sDataProc(SGChannel channel, Ptr p, long length, long *offset, long chRefCon, TimeValue time, short writeType, long refcon)
282 {
283  return ((CQuicktimeCapture *) refcon)->dataProc(channel, p, length);
284 }
285 
286 OSErr CQuicktimeCapture::dataProc(SGChannel channel, Ptr p, long length)
287 {
288  if (!imgDesc)
289  {
290  imgDesc = (ImageDescriptionHandle) NewHandle(0);
291  SGGetChannelSampleDescription(videoChannel, (Handle) imgDesc);
292  }
293 
294  m_pBuffer = p;
295  m_lImageLength = length;
296  m_bImagePending = true;
297 
298  return noErr;
299 }
ImageType type
The type of the image.
Definition: ByteImage.h:292
int width
The width of the image in pixels.
Definition: ByteImage.h:257
int height
The height of the image in pixels.
Definition: ByteImage.h:264
CQuicktimeCapture(VideoMode mode, const char *pComponentName=0)
unsigned char * pixels
The pointer to the the pixels.
Definition: ByteImage.h:283
bool CaptureImage(CByteImage **ppImages)
Data structure for the representation of 8-bit grayscale images and 24-bit RGB (or HSV) color images ...
Definition: ByteImage.h:80