UVC host library
Dependents: LifeCam WebcamServer
Diff: uvc/usb_mjpeg.cpp
- Revision:
- 0:b0f04c137829
- Child:
- 2:812d604caad4
diff -r 000000000000 -r b0f04c137829 uvc/usb_mjpeg.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uvc/usb_mjpeg.cpp Tue Jul 31 13:58:03 2012 +0000 @@ -0,0 +1,143 @@ +#include "mbed.h" +#include "usb_mjpeg.h" +//#define __DEBUG +#define __DEBUG2 +#include "mydbg.h" +#include "Utils.h" +#include "myjpeg.h" + +#ifdef __DEBUG +extern DigitalOut led4; +#endif // __DEBUG + +#define MJPEG_FID 0x01 +#define MJPEG_EOF 0x02 +#define MJPEG_PTS 0x04 +#define MJPEG_SCR 0x08 +#define MJPEG_STI 0x20 +#define MJPEG_ERR 0x40 +#define MJPEG_EOH 0x80 + + +usb_mjpeg::usb_mjpeg(uint8_t* buf, int size) +{ + DBG_ASSERT(size >= 1024 && size <= 16000); + m_size = size; + m_seq = 0; + m_buf = buf; + ReportErrorFID = 0; + ReportErrorPTS = 0; +} + +usb_mjpeg::~usb_mjpeg() +{ + +} + +void usb_mjpeg::input(uint16_t frame, uint8_t* buf, int len) +{ + uint8_t* StreamHeader = buf; + DBG_ASSERT(buf); + if (len > 12) { + //DBG_PRINTF("%d %02X %d\n", frame, buf[1], len); + //DBG_HEX(buf, len); + DBG_ASSERT(StreamHeader[0] == 0x0c); + //DBG_ASSERT(buf[1] == 0x8c || buf[1] == 0x8d); + //DBG("bfh:%02X\n", buf[1]); + } + DBG_ASSERT(len >= 2); + + int hle = StreamHeader[0]; + uint8_t bfh = StreamHeader[1]; + DBG_ASSERT(len >= hle); + DBG_ASSERT(hle == 12); + uint8_t* data = buf + hle; + int data_len = len - hle; + if (m_seq == 0) { + if (check_SOI(buf, len)) { + DBG_PRINTF("%04X SOI\n", frame); + DBG_BYTES("SOI", buf, 16); + _open(); + m_bfh = bfh; // save FID + if (bfh & MJPEG_PTS) { + m_pts = LE32(StreamHeader+2); // save PTS + } + _wrtie(data, data_len); + m_seq++; + } + } else if (m_seq == 1) { + if (len > hle) { + _wrtie(data, data_len); + } + if (check_EOI(buf, len)) { + DBG_PRINTF("%04X EOI\n", frame); + DBG_BYTES("EOI", buf, 12); + _close(); + m_seq = 2; // done + } else if ((m_bfh ^ bfh) & MJPEG_FID) { + ReportErrorFID++; + DBG("ReportErrorFID=%d\n", ReportErrorFID); + m_seq = 0; // restart + } else if ((bfh & MJPEG_PTS) && m_pts != LE32(StreamHeader+2)) { + ReportErrorPTS++; + DBG("ReportErrorPTS=%d\n", ReportErrorPTS); + m_seq = 0; // restart + } + } else { // done + } + DBG_LED4(buf[1] & MJPEG_FID); // FID +} + +int usb_mjpeg::status() +{ + if (m_seq <= 1) { + return USBERR_PROCESSING; + } + return m_pos; +} + +bool usb_mjpeg::check_SOI(uint8_t* buf, int len) +{ + if (len >= (12+2)) { + if (buf[12] == 0xff && buf[13] == 0xd8) { + return true; + } + } + return false; +} + +bool usb_mjpeg::check_EOI(uint8_t* buf, int len) +{ + if (len >= 12) { + if (buf[1] & MJPEG_EOF) { + return true; + } + } + return false; +} + +void usb_mjpeg::_open() +{ + m_pos = 0; +} + +void usb_mjpeg::_wrtie(uint8_t* buf, int len) +{ + if (m_buf == NULL) { + return; + } + for(int i = 0; i < len && m_pos < m_size; i++) { + m_buf[m_pos++] = buf[i]; + } +} + +void usb_mjpeg::_close() +{ + //DBG("m_pos=%d\n", m_pos); + //DBG_HEX(m_buf, m_pos); + myjpeg JPEG(m_buf, m_pos, m_size); + JPEG.analytics(); + if (JPEG.DHT_pos == 0) { + m_pos = JPEG.insertDHT(); + } +}