UVC host library
Dependents: LifeCam WebcamServer
uvc/uvc.cpp
- Committer:
- va009039
- Date:
- 2012-07-31
- Revision:
- 0:b0f04c137829
File content as of revision 0:b0f04c137829:
#include "mbed.h" #include "uvc.h" //#define __DEBUG //#define __DEBUG3 #include "mydbg.h" #include "usb_itd.h" uvc::uvc(int cam) { DBG("cam=%d\n", cam); DBG_ASSERT(cam >= 0); m_cam = cam; m_init = false; m_connect = false; m_int_seq = 0; m_iso_seq = 0; m_width = 0; m_height = 0; m_payload = PAYLOAD_MJPEG; m_FormatIndex = 0; m_FrameIndex = 0; m_FrameInterval = 0; m_PacketSize = 0; m_stream = NULL; for(int i = 0; i <= 15; i++) { ReportConditionCode[i] = 0; } clearOnResult(); } uvc::~uvc() { clearOnResult(); } int uvc::setup() { if (!m_init) { return _init(); } return 0; } int uvc::get_jpeg(const char* path) { const int size = 4800; const int timeout = 5000; uint8_t* buf = new uint8_t[size]; DBG_ASSERT(buf); if (buf == NULL) { return -1; } usb_mjpeg mjpeg(buf, size); attach(&mjpeg); Timer t; t.reset(); t.start(); while(t.read_ms() < timeout) { int stat = isochronous(); if (mjpeg.status() >= 0) { break; } } detach(); int len = mjpeg.status(); if (len >= 0) { if (path != NULL) { FILE *fp = fopen(path, "wb"); if (fp != NULL) { for(int i = 0; i < len; i++) { fputc(buf[i], fp); } fclose(fp); } } } delete[] buf; return len; } int uvc::get_jpeg(uint8_t* buf, int size) { //DBG("buf=%p size=%d\n", buf, size); const int timeout = 5000; usb_mjpeg mjpeg(buf, size); attach(&mjpeg); Timer t; t.reset(); t.start(); while(t.read_ms() < timeout) { int stat = isochronous(); if (mjpeg.status() >= 0) { break; } } detach(); int len = mjpeg.status(); return len; } bool uvc::interrupt() { if (!m_init) { _init(); } if (m_int_seq == 0) { int rc = m_pEpIntIn->transfer(m_int_buf, sizeof(m_int_buf)); if (rc != USBERR_PROCESSING) { return false; } m_int_seq++; } int len = m_pEpIntIn->status(); if (len > 0) { m_int_seq = 0; DBG_BYTES("interrupt", m_int_buf, len); return true; } return false; } #define CC_NOERROR 0x0 #define CC_DATAOVERRUN 0x8 #define CC_DATAUNDERRUN 0x9 inline void DI() { NVIC_DisableIRQ(USB_IRQn); } inline void EI() { NVIC_EnableIRQ(USB_IRQn); } int uvc::isochronous() { if (m_iso_seq == 0) { uint16_t frame = LPC_USB->HcFmNumber; m_iso_frame = frame + 10; // 10msec DBG_ASSERT(m_pEpIsoIn->m_itdActive == 0); m_iso_seq++; } if (m_iso_seq == 1) { DBG_ASSERT(m_itdCount > 0 && m_itdCount <= 8); while(m_pEpIsoIn->m_itdActive < m_itdCount) { int len = m_PacketSize * m_FrameCount; uint8_t* buf = (uint8_t*)usb_get_bp(len); if (buf == NULL) { DBG("len=%d\n", len); DBG("m_itdCount=%d\n", m_itdCount); } DBG_ASSERT(buf); int rc = m_pEpIsoIn->transfer(m_iso_frame, m_FrameCount, buf, len); m_iso_frame += m_FrameCount; DBG_ASSERT(rc == USBERR_PROCESSING); } m_iso_seq++; } if (m_iso_seq == 2) { //DBG("frame:%04X\n", LPC_USB->HcFmNumber); while(1) { DI(); bool empty = m_pEpIsoIn->queue_done_itd.empty(); EI(); if (empty) { break; } DI(); HCITD* itd = m_pEpIsoIn->queue_done_itd.front(); m_pEpIsoIn->queue_done_itd.pop(); EI(); m_pEpIsoIn->m_itdActive--; usb_itd iso_td(itd); //DBG("frame:%04X\n", LPC_USB->HcFmNumber); //DBG("itd->Control=%08X\n", itd->Control); int cc = iso_td.ConditionCode(); DBG_ASSERT(cc >= 0 && cc <= 15); ReportConditionCode[cc]++; if (cc != CC_NOERROR) { DBG3("%04X ERR:%X\n", LPC_USB->HcFmNumber, cc); iso_td.free(); m_iso_seq = 3; return -1; } uint16_t frame = iso_td.StartingFrame(); int fc = iso_td.FrameCount(); for(int i = 0; i < fc; i++) { int len = iso_td.Length(i); if (len > 0) { if (m_stream) { m_stream->input(frame+i, iso_td.BufferPage(i, m_PacketSize), len); } onResult(frame+i, iso_td.BufferPage(i, m_PacketSize), len); } } iso_td.free(); } //DBG("frame:%04X\n", LPC_USB->HcFmNumber); m_iso_seq = 1; return m_pEpIsoIn->m_itdActive; } if (m_iso_seq == 3) { // cleanup DBG("m_pEpIsoIn->queue_done_itd.size() :%d\n", m_pEpIsoIn->queue_done_itd.size()); while(1) { DI(); bool empty = m_pEpIsoIn->queue_done_itd.empty(); EI(); if (empty) { break; } DI(); HCITD* itd = m_pEpIsoIn->queue_done_itd.front(); m_pEpIsoIn->queue_done_itd.pop(); EI(); m_pEpIsoIn->m_itdActive--; usb_itd iso_td(itd); iso_td.free(); } if (m_pEpIsoIn->m_itdActive == 0) { m_iso_seq = 0; } } return m_pEpIsoIn->m_itdActive; } void uvc::attach(usb_stream* stream) { m_stream = stream; } void uvc::detach() { m_stream = NULL; } void uvc::onResult(uint16_t frame, uint8_t* buf, int len) { if(m_pCbItem && m_pCbMeth) (m_pCbItem->*m_pCbMeth)(frame, buf, len); else if(m_pCb) m_pCb(frame, buf, len); } void uvc::setOnResult( void (*pMethod)(uint16_t, uint8_t*, int) ) { m_pCb = pMethod; m_pCbItem = NULL; m_pCbMeth = NULL; } void uvc::clearOnResult() { m_pCb = NULL; m_pCbItem = NULL; m_pCbMeth = NULL; }