video streaming using websocket. but,streaming is very slower than 0.1fps.

Dependencies:   BaseUsbHost EthernetInterface WebSocketClient mbed-rtos mbed

Fork of BaseUsbHost_example by Norimasa Okamoto

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers UvcCam.cpp Source File

UvcCam.cpp

00001 // UvcCam.cpp 2013/2/11
00002 #include "mbed.h"
00003 #include "rtos.h"
00004 #include "BaseUsbHost.h"
00005 //#define DEBUG
00006 #include "BaseUsbHostDebug.h"
00007 #define TEST
00008 #include "BaseUsbHostTest.h"
00009 #include "UvcCam.h"
00010 #include <string>
00011 
00012 UvcCam::UvcCam(int formatIndex, int frameIndex, uint32_t interval, ControlEp* ctlEp)
00013 {
00014     uint8_t buf[34];
00015     int rc;
00016     int alt;
00017     int cfg2;
00018     
00019     if (ctlEp == NULL) { // root hub
00020         DBG_OHCI(LPC_USB->HcRhPortStatus1);
00021         TEST_ASSERT_FALSE(LPC_USB->HcRhPortStatus1 & 0x200);
00022         ctlEp = new ControlEp();
00023         TEST_ASSERT_TRUE(ctlEp);
00024     }
00025     bool r = check(ctlEp);
00026     TEST_ASSERT(r);
00027     m_ctlEp = ctlEp;
00028 
00029     rc = ctlEp->GetDescriptor(1, 0, buf, sizeof(StandardDeviceDescriptor));
00030     TEST_ASSERT(rc == USB_OK);
00031     StandardDeviceDescriptor* sd = reinterpret_cast<StandardDeviceDescriptor*>(buf);
00032     VERBOSE("vid: %04x\n", sd->idVendor); 
00033     VERBOSE("pid: %04x\n", sd->idProduct);
00034     string s = ctlEp->GetStringDescriptor(sd->iManufacturer);
00035     VERBOSE("iManufacturer: %s\n", s.c_str());
00036     s = ctlEp->GetStringDescriptor(sd->iProduct);
00037     VERBOSE("iProduct: %s\n", s.c_str());
00038     vid = sd->idVendor;
00039     pid = sd->idProduct;
00040     
00041     UvcCfg* cfg = new UvcCfg(formatIndex, frameIndex, ctlEp);
00042     TEST_ASSERT(cfg);
00043 
00044     int param_len = 34;
00045     TEST_ASSERT(cfg->bcdUVC >= 0x0100);
00046     if (cfg->bcdUVC == 0x0100) { // UVC ver. 1.0
00047         param_len = 26;
00048     }
00049     
00050     int addr = m_ctlEp->GetAddr();
00051     m_isoEp = new IsochronousEp(addr, cfg->bEndpointAddress, cfg->wMaxPacketSize);
00052     TEST_ASSERT_TRUE(m_isoEp);
00053 
00054 //#define USE_PROBE
00055 
00056 #ifdef USE_PROBE
00057     rc = Control(GET_INFO, VS_PROBE_CONTROL, 1, buf, 1);
00058     TEST_ASSERT(rc == USB_OK);
00059     DBG_BYTES("GET_INFO Prob", buf, 1);
00060 
00061     rc = Control(GET_DEF, VS_PROBE_CONTROL, 1, buf, param_len);
00062     TEST_ASSERT(rc == USB_OK);
00063     DBG_BYTES("GET_DEF Probe", buf, param_len);
00064 
00065     rc = Control(GET_MIN, VS_PROBE_CONTROL, 1, buf, param_len);
00066     TEST_ASSERT(rc == USB_OK);
00067     DBG_BYTES("GET_MIN Probe", buf, param_len);
00068 
00069     rc = Control(GET_MAX, VS_PROBE_CONTROL, 1, buf, param_len);
00070     TEST_ASSERT(rc == USB_OK);
00071     DBG_BYTES("GET_MAX Probe", buf, param_len);
00072 
00073     rc = Control(GET_CUR, VS_PROBE_CONTROL, 1, buf, param_len);
00074     TEST_ASSERT(rc == USB_OK);
00075     DBG_BYTES("GET_CUR Probe", buf, param_len);
00076 #endif // USE_PROBE
00077 
00078     rc = Control(GET_INFO, VS_COMMIT_CONTROL, 1, buf, 1);
00079     TEST_ASSERT(rc == USB_OK);
00080     DBG_BYTES("GET_INFO Commit", buf, 1);
00081 
00082     memset(buf, 0, param_len);
00083     buf[2] = cfg->FormatIndex;
00084     buf[3] = cfg->FrameIndex;
00085     *reinterpret_cast<uint32_t*>(buf+4) = interval;
00086     
00087     DBG_BYTES("SET_CUR Commit", buf, param_len);
00088     rc = Control(SET_CUR, VS_COMMIT_CONTROL, 1, buf, param_len);
00089     TEST_ASSERT(rc == USB_OK);
00090 
00091     rc = Control(GET_CUR, VS_COMMIT_CONTROL, 1, buf, param_len);
00092     TEST_ASSERT(rc == USB_OK);
00093     TEST_ASSERT_EQUAL(buf[2], cfg->FormatIndex);
00094     TEST_ASSERT_EQUAL(buf[3], cfg->FrameIndex);
00095     TEST_ASSERT_EQUAL(*reinterpret_cast<uint32_t*>(buf+4), interval);
00096     DBG_BYTES("GET_CUR Commit", buf, param_len);
00097 
00098     rc = m_ctlEp->GetConfiguration(&cfg2);
00099     TEST_ASSERT_EQUAL(rc, USB_OK);
00100     DBG("config: %d\n", cfg2);
00101 
00102     rc = m_ctlEp->SetConfiguration(1);
00103     TEST_ASSERT_EQUAL(rc, USB_OK);
00104 
00105     rc = m_ctlEp->GetConfiguration(&cfg2);
00106     TEST_ASSERT_EQUAL(rc, USB_OK);
00107     DBG("config: %d\n", cfg2);
00108     TEST_ASSERT_EQUAL(cfg2, 1);
00109 
00110     rc = m_ctlEp->GetInterface(cfg->bInterface, &alt);
00111     TEST_ASSERT_EQUAL(rc, USB_OK);
00112     DBG("alt: %d\n", alt);
00113 
00114     rc = m_ctlEp->SetInterfaceAlternate(cfg->bInterface, cfg->bAlternate);
00115     TEST_ASSERT_EQUAL(rc, USB_OK);
00116 
00117     rc = m_ctlEp->GetInterface(cfg->bInterface, &alt);
00118     TEST_ASSERT_EQUAL(rc, USB_OK);
00119     DBG("alt: %d\n", alt);
00120     TEST_ASSERT_EQUAL(alt, cfg->bAlternate);
00121     delete cfg;
00122     
00123     for(int i = 0; i < 16; i++) {
00124         report_cc_count[i] = 0;
00125         report_ps_cc_count[i] = 0;
00126     }
00127   
00128     LPC_USB->HcControl |= OR_CONTROL_PLE; // PeriodicListEnable
00129     LPC_USB->HcControl |= OR_CONTROL_IE;  // IsochronousEnable
00130 }
00131 
00132 bool UvcCam::check(ControlEp* ctlEp)
00133 {
00134     if (ctlEp == NULL) {
00135         return false;
00136     }
00137     uint8_t buf[18];
00138     int r = ctlEp->GetDescriptor(1, 0, buf, 8);
00139     if (r != USB_OK) {
00140         return false;
00141     }
00142     DBG_HEX(buf, 8);
00143     const uint8_t desc[] = {0x12,0x01,0x00,0x02,0xef,0x02,0x01};
00144     if (memcmp(buf, desc, sizeof(desc)) != 0) {
00145         return false;
00146     }
00147     r = ctlEp->GetDescriptor(1, 0, buf, sizeof(buf));
00148     if (r != USB_OK) {
00149         return false;
00150     }
00151     DBG_HEX(buf, 18);
00152     return true;
00153 }
00154 
00155 #define  DESCRIPTOR_TYPE_DEVICE        1
00156 #define  DESCRIPTOR_TYPE_CONFIGURATION 2
00157 #define  DESCRIPTOR_TYPE_STRING        3
00158 #define  DESCRIPTOR_TYPE_INTERFACE     4
00159 #define  DESCRIPTOR_TYPE_ENDPOINT      5
00160 
00161 #define DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION 0x0b
00162 
00163 #define DESCRIPTOR_TYPE_HID          0x21
00164 #define DESCRIPTOR_TYPE_REPORT       0x22
00165 #define DESCRIPTOR_TYPE_PHYSICAL     0x23
00166 #define DESCRIPTOR_TYPE_CS_INTERFACE 0x24
00167 #define DESCRIPTOR_TYPE_CS_ENDPOINT  0x25
00168 #define DESCRIPTOR_TYPE_HUB          0x29
00169 
00170 #define CLASS_AUDIO 0x02
00171 #define CLASS_HUB   0x09
00172 
00173 #define IF_EQ_THEN_PRINTF(A,B) if (A == B) {VERBOSE("%s\n", #A);
00174 #define ENDIF }
00175 
00176 #define CC_AUDIO 0x01
00177 #define SC_AUDIOCONTROL   0x01
00178 #define SC_AUDIOSTREAMING 0x02
00179 
00180 #define AC_HEADER          0x01
00181 #define AC_INPUT_TERMINAL  0x02
00182 #define AC_OUTPUT_TERMINAL 0x03
00183 #define AC_FEATURE_UNIT    0x06
00184 
00185 // Input Terminal Types
00186 #define ITT_CAMERA 0x0201
00187 
00188 static int LE16(const uint8_t* d)
00189 {
00190     return d[0] | (d[1] << 8);
00191 }
00192 
00193 static int LE24(const uint8_t* d) {
00194     return d[0] | (d[1]<<8) | (d[2] << 16);
00195 }
00196 
00197 static int LE32(const uint8_t* d) {
00198     return d[0] |(d[1]<<8) | (d[2] << 16) |(d[3] << 24) ;
00199 }
00200 
00201 struct GUID {
00202     uint8_t data[16];
00203     string to_string() {
00204         string s;
00205         for(int i = 0; i < 16; i++) {
00206             char buf[3];
00207             snprintf(buf, sizeof(buf), "%02x", data[i]);
00208             s += buf;
00209             if (i == 3 || i == 5 || i == 7 || i == 9) {
00210                 s += "-";
00211             }
00212         }
00213         return s;
00214     }
00215     bool isFormat(const char* fmt) {
00216         int len = strlen(fmt);
00217         return memcmp(data, fmt, len) == 0;
00218     }
00219 };
00220 
00221 UvcCfg::UvcCfg(int formatIndex, int frameIndex, ControlEp* ctlEp):wMaxPacketSize(0),_ctlEp(ctlEp)
00222 {
00223     TEST_ASSERT(ctlEp);
00224     switch(formatIndex) {
00225         case UVC_MJPEG: _payload = UVC_MJPEG; break;
00226         case UVC_YUY2:  _payload = UVC_YUY2; break;
00227         default:        _payload = UVC_MJPEG; break;
00228     }
00229 
00230     switch(frameIndex) {
00231         case UVC_160x120: _width = 160; _height = 120; break;
00232         case UVC_176x144: _width = 176; _height = 144; break;
00233         case UVC_320x176: _width = 320; _height = 176; break;
00234         case UVC_320x240: _width = 320; _height = 240; break;
00235         case UVC_352x288: _width = 352; _height = 288; break;
00236         case UVC_432x240: _width = 432; _height = 240; break;
00237         case UVC_640x480: _width = 640; _height = 480; break;
00238         case UVC_544x288: _width = 544; _height = 288; break;
00239         case UVC_640x360: _width = 640; _height = 360; break;
00240         case UVC_752x416: _width = 752; _height = 416; break;
00241         case UVC_800x448: _width = 800; _height = 448; break;
00242         case UVC_800x600: _width = 800; _height = 600; break;
00243         default:          _width = 160; _height = 120; break;
00244     }
00245     int index = 0;
00246     uint8_t temp[4];
00247     int rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, index, temp, sizeof(temp));
00248     TEST_ASSERT(rc == USB_OK);
00249     DBG_BYTES("Config Descriptor 4bytes", temp, sizeof(temp));
00250     TEST_ASSERT(temp[0] == 9);
00251     TEST_ASSERT(temp[1] == 0x02);
00252     int TotalLength = LE16(temp+2);
00253     DBG("TotalLength: %d\n", TotalLength);
00254 
00255     uint8_t* buf = new uint8_t[TotalLength];
00256     TEST_ASSERT(buf);
00257     rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, index, buf, TotalLength);
00258     TEST_ASSERT(rc == USB_OK);
00259     if (rc != USB_OK) {
00260         delete[] buf;
00261         return;
00262     }
00263     _parserConfigurationDescriptor(buf, TotalLength);
00264     delete[] buf;
00265 }
00266 
00267 void UvcCfg::_parserAudioControl(uint8_t* buf, int len) {
00268     int subtype = buf[2];
00269     IF_EQ_THEN_PRINTF(AC_HEADER, subtype)
00270     VERBOSE("ADC: %04x\n", LE16(buf+3));
00271     VERBOSE("TotalLength: %d\n", LE16(buf+5));
00272     VERBOSE("InCollection: %d\n", buf[7]);
00273     for (int n = 1; n <= buf[7]; n++) {
00274         VERBOSE("aInterfaceNr(%d): %d\n", n, buf[8+n-1]);
00275     }
00276     ENDIF
00277     IF_EQ_THEN_PRINTF(AC_INPUT_TERMINAL, subtype)
00278     VERBOSE("TerminalID: %d\n", buf[3]);
00279     VERBOSE("TerminalType: %04X\n", LE16(buf+4));
00280     VERBOSE("AssocTermianl: %d\n", buf[6]);
00281     VERBOSE("NrChannels: %d\n", buf[7]);
00282     ENDIF
00283     IF_EQ_THEN_PRINTF(AC_OUTPUT_TERMINAL, subtype)
00284     VERBOSE("TerminalID: %d\n", buf[3]);
00285     VERBOSE("TerminalType: %04X\n", LE16(buf+4));
00286     VERBOSE("AssocTermianl: %d\n", buf[6]);
00287     ENDIF
00288     IF_EQ_THEN_PRINTF(AC_FEATURE_UNIT, subtype)
00289     VERBOSE("UnitID: %d\n", buf[3]);
00290     VERBOSE("SourceID: %d\n", buf[4]);
00291     VERBOSE("ControlSize: %d\n", buf[5]);
00292     ENDIF
00293 }
00294 
00295 #define AS_GENERAL     0x01
00296 #define AS_FORMAT_TYPE 0x02
00297 
00298 void UvcCfg::_parserAudioStream(uint8_t* buf, int len) {
00299     int subtype = buf[2];
00300     IF_EQ_THEN_PRINTF(AS_GENERAL, subtype)
00301     VERBOSE("TerminalLink: %d\n", buf[3]);
00302     VERBOSE("Delay: %d\n", buf[4]);
00303     VERBOSE("FormatTag: %04x\n", LE16(buf+5));
00304     ENDIF
00305     IF_EQ_THEN_PRINTF(AS_FORMAT_TYPE, subtype)
00306     VERBOSE("FormatType: %d\n", buf[3]);
00307     VERBOSE("NrChannels: %d\n", buf[4]);
00308     VERBOSE("SubFrameSize: %d\n", buf[5]);
00309     VERBOSE("BitResolution: %d\n", buf[6]);
00310     VERBOSE("SamFreqType: %d\n", buf[7]);
00311     VERBOSE("SamFreq(1): %d\n", LE24(buf+8));
00312     ENDIF
00313 }
00314 
00315 #define CC_VIDEO 0x0e
00316 
00317 #define SC_VIDEOCONTROL   0x01
00318 #define SC_VIDEOSTREAMING 0x02
00319 
00320 #define VC_HEADER          0x01
00321 #define VC_INPUT_TERMINAL  0x02
00322 #define VC_OUTPUT_TERMINAL 0x03
00323 #define VC_SELECTOR_UNIT   0x04
00324 #define VC_PROCESSING_UNIT 0x05
00325 #define VC_EXTENSION_UNIT  0x06
00326 
00327 void UvcCfg::_parserVideoControl(uint8_t* buf, int len) {
00328     int subtype = buf[2];
00329     IF_EQ_THEN_PRINTF(VC_HEADER, subtype)
00330         bcdUVC = LE16(buf+3);
00331         VERBOSE("UVC: %04x\n", bcdUVC);
00332         VERBOSE("TotalLength: %d\n", LE16(buf+5));
00333         VERBOSE("ClockFrequency: %d\n", LE32(buf+7));
00334         VERBOSE("InCollection: %d\n", buf[11]);
00335         VERBOSE("aInterfaceNr(1): %d\n", buf[12]);
00336     ENDIF
00337     IF_EQ_THEN_PRINTF(VC_INPUT_TERMINAL, subtype)
00338         VERBOSE("TerminalID: %d\n", buf[3]);
00339         uint16_t tt = LE16(buf+4);
00340         VERBOSE("TerminalType: %04X\n", tt);
00341         VERBOSE("AssocTerminal: %d\n", buf[6]);
00342         VERBOSE("Terminal: %d\n", buf[7]);
00343         if (tt == ITT_CAMERA) { // camera
00344             int bControlSize = buf[14];
00345             VERBOSE("ControlSize: %d\n", bControlSize);
00346             for(int i = 0; i < bControlSize; i++) {
00347             uint8_t bControls = buf[15+i];
00348                 VERBOSE("Controls(%d): %02X\n", i, bControls); 
00349             }
00350         }
00351     ENDIF
00352     IF_EQ_THEN_PRINTF(VC_OUTPUT_TERMINAL, subtype)
00353         VERBOSE("TerminalID: %d\n", buf[3]);
00354         VERBOSE("TerminalType: %04X\n", LE16(buf+4));
00355         VERBOSE("AssocTerminal: %d\n", buf[6]);
00356         VERBOSE("SourceID: %d\n", buf[7]);
00357         VERBOSE("Terminal: %d\n", buf[8]);
00358     ENDIF
00359     IF_EQ_THEN_PRINTF(VC_SELECTOR_UNIT, subtype)
00360         VERBOSE("UnitID: %d\n", buf[3]);
00361     ENDIF
00362     IF_EQ_THEN_PRINTF(VC_PROCESSING_UNIT, subtype)
00363         VERBOSE("UnitID: %d\n", buf[3]);
00364         VERBOSE("SourceID: %d\n", buf[4]);
00365         VERBOSE("MaxMultiplier: %d\n", LE16(buf+5));
00366         VERBOSE("ControlSize: %d\n", buf[7]);
00367         int pos = 8;
00368         for (int n = 1; n <= buf[7]; n++) {
00369             VERBOSE("Controls(%d): %02X\n", n , buf[pos]);
00370             pos++;
00371         }
00372         VERBOSE("Processing: %d\n", buf[pos]);
00373         pos++;
00374         VERBOSE("VideoStanders: %02X\n", buf[pos]);
00375     ENDIF
00376     IF_EQ_THEN_PRINTF(VC_EXTENSION_UNIT, subtype)
00377         VERBOSE("UnitID: %d\n", buf[3]);
00378         GUID* guid = reinterpret_cast<GUID*>(buf+4);
00379         string s = guid->to_string();
00380         VERBOSE("guidExtensionCode: %s\n", s.c_str());
00381         VERBOSE("NumControls: %d\n", buf[20]);
00382         int p = buf[21];
00383         VERBOSE("NrInPins: %d\n", p);
00384         int pos = 22;
00385         for (int n = 1; n <= p; n++) {
00386             VERBOSE("SourceID(%d): %d\n", n, buf[pos]);
00387             pos++;
00388         }
00389         int bControlSize = buf[pos];
00390         pos++;
00391         VERBOSE("ControlSize: %d\n", bControlSize);
00392         pos++;
00393         for(int i = 0; i < bControlSize; i++) {
00394             VERBOSE("Control(%d): %02X\n", i, buf[pos]);
00395             pos++;
00396         }
00397         VERBOSE("iExtension: %d\n", buf[pos]);
00398     ENDIF
00399 }
00400 
00401 #define VS_INPUT_HEADER 0x01
00402 #define VS_STILL_FRAME  0x03
00403 #define VS_FORMAT_UNCOMPRESSED 0x04
00404 #define VS_FRAME_UNCOMPRESSED 0x05
00405 #define VS_FORMAT_MJPEG 0x06
00406 #define VS_FRAME_MJPEG  0x07
00407 #define VS_COLOR_FORMAT 0x0d
00408 
00409 void UvcCfg::_parserVideoStream(uint8_t* buf, int len) {
00410     int subtype = buf[2];
00411     IF_EQ_THEN_PRINTF(VS_INPUT_HEADER, subtype)
00412         VERBOSE("NumFormats: %d\n", buf[3]);
00413         VERBOSE("TotalLength: %d\n", LE16(buf+4));
00414         VERBOSE("EndpointAddress: %02X\n", buf[6]);
00415         VERBOSE("Info: %02X\n", buf[7]);
00416         VERBOSE("TerminalLink: %d\n", buf[8]);
00417         VERBOSE("StillCaptureMethod: %d\n", buf[9]);
00418         VERBOSE("TriggerSupport: %d\n", buf[10]);
00419         VERBOSE("TriggerUsage: %d\n", buf[11]);
00420         VERBOSE("ControlSize: %d\n", buf[12]);
00421         int pos = 13;
00422         for (int n = 1; n <= buf[12]; n++) {
00423             VERBOSE("Controls(%d): %02X\n", n, buf[pos]);
00424             pos++;
00425         }
00426         bEndpointAddress = buf[6];
00427     ENDIF
00428     IF_EQ_THEN_PRINTF(VS_STILL_FRAME, subtype)
00429     VERBOSE("EndpointAdress: %02X\n", buf[3]);
00430     VERBOSE("NumImageSizePatterns: %d\n", buf[4]);
00431     int ptn = buf[4];
00432     int pos = 5;
00433     for (int n = 1; n <= ptn; n++) {
00434         VERBOSE("Width(%d): %d\n", n, LE16(buf+pos));
00435         VERBOSE("Height(%d): %d\n", n, LE16(buf+pos+2));
00436         pos += 4;
00437     }
00438     VERBOSE("NumCompressPtn: %d\n", buf[pos]);
00439     ptn = buf[pos++];
00440     for (int n = 1; n <= ptn; n++) {
00441         VERBOSE("Compress(%d): %d\n", n, buf[pos]);
00442         pos++;
00443     }
00444     ENDIF
00445     IF_EQ_THEN_PRINTF(VS_FORMAT_UNCOMPRESSED, subtype)
00446         VERBOSE("FormatIndex: %d\n", buf[3]);
00447         VERBOSE("NumFrameDescriptors: %d\n", buf[4]);
00448         GUID* guid = reinterpret_cast<GUID*>(buf+5);
00449         string s = guid->to_string();
00450         if (guid->isFormat("YUY2")) {
00451             VERBOSE("GUID: %s YUY2\n", s.c_str());
00452         } else if (guid->isFormat("NV12")) {
00453             VERBOSE("GUID: %s NV12\n", s.c_str());
00454         } else {
00455             VERBOSE("GUID: %s\n", s.c_str());
00456         }
00457         VERBOSE("DefaultFrameIndex: %d\n", buf[22]);
00458         if (_payload == UVC_YUY2) {
00459             FormatIndex = buf[3];
00460         }
00461     ENDIF
00462     IF_EQ_THEN_PRINTF(VS_FRAME_UNCOMPRESSED, subtype)
00463         VERBOSE("FrameIndex: %d\n", buf[3]);
00464         VERBOSE("Capabilites: %d\n", buf[4]);
00465         VERBOSE("Width: %d\n", LE16(buf+5));
00466         VERBOSE("Height: %d\n", LE16(buf+7));
00467         VERBOSE("MinBitRate: %d\n", LE32(buf+9));
00468         VERBOSE("MaxBitRate: %d\n", LE32(buf+13));
00469         VERBOSE("MaxVideoFrameBufferSize: %d\n", LE32(buf+17));
00470         VERBOSE("DefaultFrameInterval: %d\n", LE32(buf+21));
00471         VERBOSE("FrameIntervalType: %d\n", buf[25]);
00472         int it = buf[25];
00473         uint32_t max_fi = 333333; // 30.0fps
00474         if (it == 0) {
00475             VERBOSE("FrameMinInterval: %d\n", buf[26]);
00476             VERBOSE("FrameMaxInterval: %d\n", buf[30]);
00477             VERBOSE("FrameIntervalStep: %d\n", buf[34]);
00478         } else {
00479             int pos = 26;
00480             for (int n = 1; n <= it; n++) {
00481                 uint32_t fi = LE32(buf+pos);
00482                 if (fi >= max_fi) {
00483                     max_fi = fi;
00484                 }
00485                 float fps = 1e+7 / fi;
00486                 VERBOSE("FrameInterval(%u): %d (%.1f fps)\n", n, fi, fps);
00487                 pos += 4;
00488             }
00489         }
00490         if (_payload == UVC_YUY2) {
00491             if (_width == LE16(buf+5) && _height == LE16(buf+7)) {
00492                 FrameIndex = buf[3];
00493             }
00494             if (dwFrameInterval == 0) {
00495                 dwFrameInterval = max_fi;
00496             }
00497         }
00498     ENDIF
00499     IF_EQ_THEN_PRINTF(VS_FORMAT_MJPEG, subtype)
00500         VERBOSE("FormatIndex: %d\n", buf[3]);
00501         VERBOSE("NumFrameDescriptors: %d\n", buf[4]);
00502         VERBOSE("Flags: %d\n", buf[5]);
00503         VERBOSE("DefaultFrameIndex: %d\n", buf[6]);
00504         if (_payload == UVC_MJPEG) {
00505             FormatIndex = buf[3];
00506         }
00507     ENDIF
00508     IF_EQ_THEN_PRINTF(VS_FRAME_MJPEG, subtype)
00509         VERBOSE("FrameIndex: %d\n", buf[3]);
00510         VERBOSE("Capabilites: %d\n", buf[4]);
00511         VERBOSE("Width: %d\n", LE16(buf+5));
00512         VERBOSE("Height: %d\n", LE16(buf+7));
00513         VERBOSE("MinBitRate: %d\n", LE32(buf+9));
00514         VERBOSE("MaxBitRate: %d\n", LE32(buf+13));
00515         VERBOSE("MaxVideoFrameBufferSize: %d\n", LE32(buf+17));
00516         VERBOSE("DefaultFrameInterval: %d\n", LE32(buf+21));
00517         VERBOSE("FrameIntervalType: %d\n", buf[25]);
00518         int it = buf[25];
00519         uint32_t max_fi = 333333; // 30.0fps
00520         if (it == 0) {
00521             VERBOSE("FrameMinInterval: %d\n", buf[26]);
00522             VERBOSE("FrameMaxInterval: %d\n", buf[30]);
00523             VERBOSE("FrameIntervalStep: %d\n", buf[34]);
00524         } else {
00525             int pos = 26;
00526             for (int n = 1; n <= it; n++) {
00527                 uint32_t fi = LE32(buf+pos);
00528                 if (fi >= max_fi) {
00529                     max_fi = fi;
00530                 }
00531                 float fps = 1e+7 / fi;
00532                 VERBOSE("FrameInterval(%u): %d (%.1f fps)\n", n, fi, fps);
00533                 pos += 4;
00534             }
00535         }
00536         if (_payload == UVC_MJPEG) {
00537             if (_width == LE16(buf+5) && _height == LE16(buf+7)) {
00538                 FrameIndex = buf[3];
00539             }
00540             if (dwFrameInterval == 0) {
00541                 dwFrameInterval = max_fi;
00542             }
00543         }
00544     ENDIF
00545     IF_EQ_THEN_PRINTF(VS_COLOR_FORMAT, subtype)
00546     ENDIF
00547 }
00548 
00549 void UvcCfg::_parserConfigurationDescriptor(uint8_t* buf, int len) {
00550     int pos = 0;
00551     _IfClass = 0;
00552     _IfSubClass = 0;
00553     while (pos < len) {
00554         int type = buf[pos+1];
00555         //DBG_BYTES(TYPE_Str(type), buf+pos, buf[pos]);
00556         IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_CONFIGURATION, type)
00557             VERBOSE("NumInterfaces: %d\n", buf[pos+4]);
00558         ENDIF
00559         IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, type)
00560             VERBOSE("FirstInterface: %d\n", buf[pos+2]);
00561             VERBOSE("InterfaceCount: %d\n", buf[pos+3]);
00562             VERBOSE("FunctionClass: %02X\n", buf[pos+4]);
00563             VERBOSE("FunctionSubClass: %02X\n", buf[pos+5]);
00564             VERBOSE("FunctionProtocol: %02X\n", buf[pos+6]);
00565             VERBOSE("Function: %d\n", buf[pos+7]);
00566         ENDIF
00567         IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_INTERFACE,type)
00568             VERBOSE("InterfaceNumber: %d\n", buf[pos+2]);
00569             VERBOSE("AlternateSetting: %d\n", buf[pos+3]);
00570             VERBOSE("NumEndpoint: %d\n", buf[pos+4]);
00571             VERBOSE("InterfaceClass: %02X\n", buf[pos+5]);
00572             VERBOSE("InterfaceSubClass: %02X\n", buf[pos+6]);
00573             VERBOSE("InterfaceProtocol: %02X\n", buf[pos+7]);
00574             VERBOSE("Interface: %d\n", buf[pos+8]);
00575             _If         = buf[pos+2];
00576             _Ifalt      = buf[pos+3];
00577             _IfClass    = buf[pos+5];
00578             _IfSubClass = buf[pos+6];
00579         ENDIF
00580         IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_ENDPOINT, type)
00581             VERBOSE("EndpointAddress: %02X\n", buf[pos+2]);
00582             VERBOSE("Attributes: %02X\n", buf[pos+3]);
00583             VERBOSE("MaxPacketSize: %d\n", LE16(buf+pos+4));
00584             VERBOSE("Interval: %d\n", buf[pos+6]);
00585             if (_IfClass == CC_VIDEO && _IfSubClass == SC_VIDEOSTREAMING) {
00586                 if (bEndpointAddress == buf[pos+2]) {
00587                     if (wMaxPacketSize == 0) {
00588                         wMaxPacketSize = LE16(buf+pos+4);
00589                     }    
00590                     if (wMaxPacketSize == LE16(buf+pos+4)) {
00591                         bInterface = _If;
00592                         bAlternate = _Ifalt;
00593                     }
00594                 }
00595             }
00596         ENDIF
00597         IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_CS_INTERFACE, type)
00598             IF_EQ_THEN_PRINTF(CC_VIDEO, _IfClass)
00599                 IF_EQ_THEN_PRINTF(SC_VIDEOCONTROL, _IfSubClass)
00600                     _parserVideoControl(buf+pos, buf[pos]);
00601                 ENDIF
00602                 IF_EQ_THEN_PRINTF(SC_VIDEOSTREAMING, _IfSubClass)
00603                     _parserVideoStream(buf+pos, buf[pos]);
00604                 ENDIF
00605             ENDIF
00606             IF_EQ_THEN_PRINTF(CC_AUDIO, _IfClass)
00607                 IF_EQ_THEN_PRINTF(SC_AUDIOCONTROL, _IfSubClass)
00608                     _parserAudioControl(buf+pos, buf[pos]);
00609                 ENDIF 
00610                 IF_EQ_THEN_PRINTF(SC_AUDIOSTREAMING, _IfSubClass)
00611                     _parserAudioStream(buf+pos, buf[pos]);
00612                 ENDIF
00613             ENDIF
00614         ENDIF
00615         IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_HUB, type)
00616         ENDIF
00617         pos += buf[pos];
00618     }
00619 }
00620