Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

CameraDriverQTSG.cc

Go to the documentation of this file.
00001 #if defined(__APPLE__) && !defined(__x86_64__)
00002 
00003 #include <AvailabilityMacros.h>
00004 #ifndef MAC_OS_X_VERSION_10_6
00005 
00006 #include "CameraDriverQTSG.h"
00007 #include "Shared/get_time.h"
00008 #include "Shared/debuget.h"
00009 
00010 #include <sstream>
00011 
00012 using namespace std; 
00013 
00014 const std::string CameraDriverQTSG::autoRegisterCameraDriver = DeviceDriver::getRegistry().registerType<CameraDriverQTSG>("Camera");
00015 
00016 void CameraDriverQTSG::dumpLiteral(OSType t) {
00017   union {
00018     OSType v;
00019     char s[4];
00020   } x;
00021   x.v=t;
00022   cout << x.s[3] << x.s[2] << x.s[1] << x.s[0];
00023 }
00024 
00025 void CameraDriverQTSG::updateCameraList() {
00026   if(!checkQTThreadInit()) {
00027     cerr << "CameraDriver: Couldn't initialize QuickTime" << endl;
00028     return;
00029   }
00030   
00031   // open the sequence grabber, assuming there's only ever one component of this type listed
00032   SeqGrabComponent sg = OpenDefaultComponent(SeqGrabComponentType, 0);
00033   if(sg==NULL) {
00034     cerr << "CameraDriver: Couldn't open sequence grabber" << endl;
00035     return;
00036   }
00037   
00038   OSErr err=noErr;
00039   SGChannel sgChan=NULL; // temporary channel just to get device list
00040   SGDeviceList devList = NULL; // list of capture devices
00041   try {
00042     // initialize the default sequence grabber component
00043     err = SGInitialize(sg);
00044     if(err!=noErr) throw "SGInitialize";
00045     
00046     err = SGNewChannel(sg, VideoMediaType, &sgChan);
00047     if(err!=noErr) throw "SGNewChannel";
00048     
00049     //err = SGSetChannelBounds(sgChan, &bounds);
00050     //if(err!=noErr) throw "SGSetChannelBounds";
00051     
00052     err = SGSetChannelUsage(sgChan, seqGrabRecord | seqGrabLowLatencyCapture /* | seqGrabPreview | seqGrabAlwaysUseTimeBase */);
00053     if(err!=noErr) throw "SGSetChannelUsage";
00054     
00055     // just for debugging info
00056     /*CodecNameSpecListPtr codecs;
00057     err = GetCodecNameList(&codecs,0);
00058     if(err!=noErr) cerr << "Could not get codec list" << endl;
00059     else {
00060       cout << "Codec names: " << endl;
00061       for(int i=0; i<codecs->count; ++i) {
00062         cout << '\t' << codecs->list[i].codec << ' ';
00063         dumpLiteral(codecs->list[i].cType);
00064         cout << ' ' << p2c(codecs->list[i].typeName) << endl;
00065       }
00066       DisposeCodecNameList(codecs);
00067     }*/
00068     
00069     
00070     // thanks Harald ( hxr AT users sourceforge net ) for 'wacaw' source to demonstrate
00071     // how to get the device list via sequence grabber...
00072     err = SGGetChannelDeviceList(sgChan, sgDeviceListDontCheckAvailability | sgDeviceListIncludeInputs, &devList);
00073     if(err!=noErr) throw "SGGetChannelDeviceList";
00074     
00075     // we got our list, close the channel so whatever default device it grabbed is available for the CameraSourceQTSG
00076     // (we can open SequenceGrabber component multiple times, but each channel/device only open from one place...)
00077     if(sgChan!=NULL)
00078       SGDisposeChannel(sg,sgChan);
00079     sgChan=NULL;
00080     
00081     map<string,unsigned int> nameCnt;
00082     SGDeviceListRecord& list = **devList;
00083     
00084     storage_t olddict; // need to backup old dictionary so we can delete unused entries
00085     dict.swap(olddict);
00086     storage_t::const_iterator it = olddict.find(".type");
00087     if(it!=olddict.end())
00088       dict.insert(*it);
00089     myRef.clear(); // we'll rebuild these in the following loop
00090     comments.clear();
00091     
00092     for(int i = 0; i<list.count; i++) {
00093       string devName = p2c(list.entry[i].name);
00094       //cout << "Device: " << devName << ' ' << (list.entry[i].flags & sgDeviceNameFlagDeviceUnavailable) << ' ' << (list.entry[i].flags & sgDeviceNameFlagShowInputsAsDevices) << endl;
00095       
00096       SGDeviceInputList inputList = list.entry[i].inputs;
00097       if(inputList != NULL) {
00098         SGDeviceInputListRecord& inputs = **inputList;
00099         //if(inputs.count==0)
00100           //cout << "    (no inputs)" << endl;
00101         //cout << "    There are " << inputs.count << " inputs for this device." << endl;
00102         //cout << "    The current selection is " << inputs.selectedIndex << endl;
00103         for (int j = 0; j < inputs.count; j++) {
00104           string inputName = p2c(inputs.entry[j].name);
00105           //cout << "    Input: " << inputName << ' ' << (inputs.entry[j].flags & sgDeviceInputNameFlagInputUnavailable) << endl;
00106           // heuristic hack -- take the last word which starts with an alphabet character as the "short" input name
00107           unsigned int x;
00108           for(x=inputName.size(); x>0; --x)
00109             if(isspace(inputName[x-1]) && x<inputName.size() && isalpha(inputName[x]))
00110               break;
00111           string name;
00112           while(x<inputName.size() && !isspace(inputName[x]))
00113             name+=inputName[x++];
00114           if(nameCnt[name]++ > 0) {
00115             stringstream uniqname;
00116             uniqname << name << "-" << nameCnt[name];
00117             name = uniqname.str();
00118           }
00119           //cout << "    I shall call you '" << name << "'" << endl;
00120           
00121           bool found; // go through all of the current sources looking for this input
00122           for(it=olddict.begin(); it!=olddict.end(); ++it) {
00123             if(it->first==".type")
00124               continue;
00125             CameraSourceQTSG& ds = dynamic_cast<CameraSourceQTSG&>(*it->second);
00126             // have to match the full device and input names, not the "short" name!
00127             if(ds.getDeviceName()==devName && ds.getInputName()==inputName) {
00128               found=true; // we already have an entry for this input -- reuse that instance instead of making a new one
00129               myRef.insert(dict[name] = &ds);
00130               break;
00131             }
00132           }
00133           if(!found) { // didn't find a pre-existing CameraSourceQTSG for this input
00134             // make a new one, store it in the dictionary, and add it to myRef:
00135             try {
00136               CameraSourceQTSG * cam = new CameraSourceQTSG(sg, name, devName, inputName, j);
00137               myRef.insert(dict[name] = cam);
00138             } catch(const pair<OSErr,const char *>& msg) {
00139               cerr << "CameraDriver registering: " << inputName << endl;
00140               cerr << "   on device: " << devName << endl;
00141               cerr << "     call to: " << msg.second << " returned error " << msg.first << " (attempting to continue...)" << endl;
00142               continue;
00143             }
00144           }
00145           comments[name]="Device Name: "+devName+"\nInput Name: "+inputName;
00146         }
00147       }
00148       
00149       // now go through entries of olddict
00150       // anything that isn't in dict nor myRef should be deleted
00151       // (entries may be "renamed" if bus topology changes, so might have
00152       // old entries not deleted because it's in use under a new name)
00153       for(it=olddict.begin(); it!=olddict.end(); ++it) {
00154         if(it->first==".type")
00155           continue;
00156         if(dict.find(it->first)==dict.end()) {
00157           if(myRef.find(it->second)==myRef.end())
00158             delete it->second;
00159         } else {
00160           // we shouldn't have any entries which are found in dict (i.e. in use) but not myRef
00161           ASSERT(myRef.find(it->second)!=myRef.end(), "Entry in use with unreferenced value...???");
00162         }
00163       }
00164     }
00165     
00166   } catch(const char* call) {
00167     cerr << "CameraDriver: " << call << " returned error " << err << endl;
00168   } catch(const pair<OSErr,const char *>& msg) {
00169     cerr << "CameraDriver: " << msg.second << " returned error " << msg.first << endl;
00170   }
00171   if(devList!=NULL)
00172     SGDisposeDeviceList(sg, devList);
00173   devList=NULL;
00174   if(sgChan!=NULL)
00175     SGDisposeChannel(sg,sgChan);
00176   sgChan=NULL;
00177   if(sg!=NULL)
00178     CloseComponent(sg);
00179   sg=NULL;
00180 }
00181 
00182 #endif // pre-10.6
00183 #endif // Apple 32 bit
00184 
00185 /*! @file
00186  * @brief Implements CameraDriverQTSG, which provides camera capture through QuickTime and the Sequence Grabber, now deprecated.  See the alternative CameraDriverQTKit implementation.
00187  * @author Ethan Tira-Thompson (ejt) (Creator)
00188  */

Tekkotsu Hardware Abstraction Layer 5.1CVS
Generated Mon May 9 05:01:37 2016 by Doxygen 1.6.3