Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

CameraDriverOSX.cc

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

Tekkotsu Hardware Abstraction Layer 4.0
Generated Thu Nov 22 01:00:53 2007 by Doxygen 1.5.4