huffmancode to decode in real-time for motion-jpeg

Dependents:   BaseJpegDecode_example SimpleJpegDecode_example Dumb_box_rev2

example code:

Import programBaseJpegDecode_example

BaseJpegDeocde exampe program

Import programSimpleJpegDecode_example

convert JPEG stream data to bitmap, BaseJpegDecode example program

Files at this revision

API Documentation at this revision

Comitter:
va009039
Date:
Thu Oct 25 11:00:05 2012 +0000
Parent:
0:417b7ae90eff
Child:
2:5b1dd4e34857
Commit message:
support DQT

Changed in this revision

BaseJpefDecode.cpp Show diff for this revision Revisions of this file
BaseJpegDecode.cpp Show annotated file Show diff for this revision Revisions of this file
BaseJpegDecode.h Show annotated file Show diff for this revision Revisions of this file
bjd_config.h Show annotated file Show diff for this revision Revisions of this file
--- a/BaseJpefDecode.cpp	Mon Oct 22 13:55:09 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,179 +0,0 @@
-#include "mbed.h"
-#include "BaseJpegDecode.h"
-
-#if 0
-#define DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);} while(0);
-#define DBG_WAIT(A) wait_ms(A)
-#else
-#define DBG(...)
-#define DBG_WAIT(A)
-#endif
-
-#if 1
-#define DBG_ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);};
-#else
-#define DBG_ASSERT(A) 
-#endif
-
-#define MARK_SOF 0xc0
-#define MARK_DHT 0xc4
-#define MARK_RST0 0xd0
-#define MARK_RST7 0xd7
-#define MARK_SOI 0xd8
-#define MARK_EOI 0xd9
-#define MARK_SOS 0xda
-#define MARK_DQT 0xdb
-#define MARK_DRI 0xdd
-#define MARK_APP 0xe0
-
-#define SEQ_INIT 0
-#define SEQ_MARK 1
-#define SEQ_LEN  2
-#define SEQ_LEN2 3
-#define SEQ_SKIP 4
-#define SEQ_SOS  5
-#define SEQ_SOS2 6
-
-#define HT_DC 0
-#define HT_AC 1
-
-BaseJpegDecode::BaseJpegDecode()
-{
-    m_yblocks = JPEG_MCU_YBLOCKS; // 2 or 4
-    clear();
-    pHD = new HuffmanDecode;
-}
-
-void BaseJpegDecode::clear()
-{
-    m_seq = SEQ_INIT;
-}
-
-void BaseJpegDecode::input(uint8_t* buf, int len)
-{
-    for(int i = 0; i < len; i++) {
-        input(buf[i]);
-    }
-}
-
-void BaseJpegDecode::restart()
-{
-    m_block = 0;
-    m_scan = 0;
-    m_old_DC_value[0] = 0;
-    m_old_DC_value[1] = 0;
-    m_bitpat.clear();
-    m_huff = NULL;
-}
-
-void BaseJpegDecode::input(uint8_t c)
-{
-    switch(m_seq) {
-        case SEQ_INIT:
-            if (c == 0xff) {
-                m_seq = SEQ_MARK;
-            }
-            break;
-        case SEQ_MARK:
-            outputMARK(c);
-            if (c == MARK_SOI || c == MARK_EOI) {
-                m_seq = SEQ_INIT;
-                break;
-            }
-            m_mark = c;
-            m_seq = SEQ_LEN;
-            break;
-        case SEQ_LEN:
-            m_skip = c;
-            m_seq = SEQ_LEN2;
-            break;
-        case SEQ_LEN2:
-            m_skip <<= 8;
-            m_skip |= c;
-            m_skip -= 2;
-            m_seq = SEQ_SKIP;
-            break;
-        case SEQ_SKIP:
-            if (--m_skip > 0) {
-                break;
-            }
-            if (m_mark == MARK_SOS) {
-                m_seq = SEQ_SOS;
-                m_mcu = 0;
-                restart();
-                break;
-            }
-            m_seq = SEQ_INIT;
-            break;
-        case SEQ_SOS:
-            if (c == 0xff) {
-                m_seq = SEQ_SOS2;
-                break;
-            }
-            inputScan(c);
-            break;
-        case SEQ_SOS2:
-            if (c == 0x00) {
-                inputScan(0xff);
-                m_seq = SEQ_SOS;
-                break;
-            } else if (c >= MARK_RST0 && c <= MARK_RST7) {
-                restart();
-                m_seq = SEQ_SOS;
-                break;
-            }
-            outputMARK(c);
-            m_seq = SEQ_INIT;
-            break;
-        default:
-            break;
-    }
-}
-
-void BaseJpegDecode::inputScan(uint8_t c)
-{
-    m_bitpat += c;
-    while(m_bitpat.size() > 0) {
-        int tc = (m_scan == 0) ? HT_DC : HT_AC;
-        int th = (m_block < m_yblocks) ? 0 : 1;
-        DBG("%d %d %08x %d\n", tc, th, m_bitpat.peek(32), m_bitpat.size());
-        if (m_huff == NULL) {
-            m_huff = pHD->Lookup(tc, th, &m_bitpat);
-            if (m_huff == NULL) {
-                break;
-            }
-            m_bitpat.get(m_huff->code_size); // skip code
-        }
-        if (m_huff->value_size > m_bitpat.size()) {
-            break;
-        }
-        DBG("%d %d %d %02x\n", m_huff->run, m_huff->value_size, m_huff->code_size, m_huff->code);
-        int value = pHD->getValue(m_huff, &m_bitpat);
-        if (tc == HT_DC) {
-            value += m_old_DC_value[th];
-            outputDC(m_mcu, m_block, value);
-            m_old_DC_value[th] = value;
-            m_scan++;
-        } else { // AC
-            if (m_huff->value_size == 0 && m_huff->run == 0) { // EOB
-                DBG("AC EOB\n");
-                m_scan = 64;
-            } else {
-                for(int i = 0; i < m_huff->run; i++) {
-                    outputAC(m_mcu, m_block, m_scan, 0);
-                    m_scan++;
-                }
-                outputAC(m_mcu, m_block, m_scan, value);
-                m_scan++;
-            }
-            if (m_scan >= 64) {
-                m_scan = 0;
-                if (++m_block >= (m_yblocks+2)) {
-                    m_block = 0;
-                    m_mcu++;
-                }
-            }
-        }
-        m_huff = NULL;
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BaseJpegDecode.cpp	Thu Oct 25 11:00:05 2012 +0000
@@ -0,0 +1,234 @@
+#include "mbed.h"
+#include "BaseJpegDecode.h"
+
+#if 0
+#define DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);} while(0);
+#define DBG_WAIT(A) wait_ms(A)
+#else
+#define DBG(...)
+#define DBG_WAIT(A)
+#endif
+
+#if 1
+#define DBG_ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);};
+#else
+#define DBG_ASSERT(A) 
+#endif
+
+#ifdef JPEG_USE_REPORT_CODE
+#define REPORT_CODE(A) (A)
+#else
+#define REPORT_CODE(A)
+#endif
+
+#define MARK_SOF0 0xc0
+#define MARK_DHT  0xc4
+#define MARK_RST0 0xd0
+#define MARK_RST7 0xd7
+#define MARK_SOI  0xd8
+#define MARK_EOI  0xd9
+#define MARK_SOS  0xda
+#define MARK_DQT  0xdb
+#define MARK_DRI  0xdd
+#define MARK_APP  0xe0
+
+#define SEQ_INIT     0
+#define SEQ_MARK     1
+#define SEQ_SEG_LEN  2
+#define SEQ_SEG_LEN2 3
+#define SEQ_SEG_BODY 4
+#define SEQ_SOS      5
+#define SEQ_SOS2     6
+
+#define HT_DC 0
+#define HT_AC 1
+
+BaseJpegDecode::BaseJpegDecode()
+{
+    m_yblocks = JPEG_MCU_YBLOCKS; // 2 or 4
+    clear();
+    pHD = new HuffmanDecode;
+    DBG_ASSERT(pHD);
+    qt[0] = new uint8_t[64];
+    qt[1] = new uint8_t[64];
+    DBG_ASSERT(qt[0]);
+    DBG_ASSERT(qt[1]);
+}
+
+void BaseJpegDecode::clear()
+{
+    m_seq = SEQ_INIT;
+}
+
+void BaseJpegDecode::input(uint8_t* buf, int len)
+{
+    for(int i = 0; i < len; i++) {
+        input(buf[i]);
+    }
+}
+
+void BaseJpegDecode::restart()
+{
+    m_block = 0;
+    m_scan = 0;
+    m_old_DC_value[0] = 0;
+    m_old_DC_value[1] = 0;
+    m_bitpat.clear();
+    m_huff = NULL;
+}
+
+void BaseJpegDecode::inputDQT(uint8_t c, int pos, int len)
+{
+    if (pos == 0 || pos == 65) {
+        m_param1 = c;
+        DBG_ASSERT(m_param1 == 0 || m_param1 == 1);
+    } else {
+        qt[m_param1][(pos%65)-1] = c;
+    }
+}
+
+void BaseJpegDecode::inputSOF(uint8_t c, int pos, int len)
+{
+    switch(pos) {
+        case 1:
+        case 3:
+            m_param1 = c<<8;
+            break;
+        case 2:
+            width = m_param1 | c;
+            break;
+        case 4:
+            height = m_param1 | c;
+            break;
+        case 7:
+            if (c == 0x22) {
+                m_yblocks = 4;
+            } else if (c == 0x21) {
+                m_yblocks = 2;
+            } else {
+                DBG_ASSERT(c == 0x22 || c == 0x21);
+            }
+            break;
+    }
+}
+
+void BaseJpegDecode::input(uint8_t c)
+{
+    switch(m_seq) {
+        case SEQ_INIT:
+            if (c == 0xff) {
+                m_seq = SEQ_MARK;
+            }
+            break;
+        case SEQ_MARK:
+            outputMARK(c);
+            if (c == MARK_SOI || c == MARK_EOI) {
+                m_seq = SEQ_INIT;
+                break;
+            }
+            m_mark = c;
+            m_seq = SEQ_SEG_LEN;
+            break;
+        case SEQ_SEG_LEN:
+            m_seg_len = c;
+            m_seq = SEQ_SEG_LEN2;
+            break;
+        case SEQ_SEG_LEN2:
+            m_seg_len <<= 8;
+            m_seg_len |= c;
+            m_seg_len -= 2;
+            m_seg_pos = 0;
+            m_seq = SEQ_SEG_BODY;
+            break;
+        case SEQ_SEG_BODY:
+            if (m_mark == MARK_DQT) {
+                inputDQT(c, m_seg_pos, m_seg_len);
+            } else if (m_mark == MARK_SOF0) {
+                inputSOF(c, m_seg_pos, m_seg_len);
+            }
+            if (++m_seg_pos < m_seg_len) {
+                break;
+            }
+            if (m_mark == MARK_SOS) {
+                m_seq = SEQ_SOS;
+                m_mcu = 0;
+                restart();
+                break;
+            }
+            m_seq = SEQ_INIT;
+            break;
+        case SEQ_SOS:
+            if (c == 0xff) {
+                m_seq = SEQ_SOS2;
+                break;
+            }
+            inputScan(c);
+            break;
+        case SEQ_SOS2:
+            if (c == 0x00) {
+                inputScan(0xff);
+                m_seq = SEQ_SOS;
+                break;
+            } else if (c >= MARK_RST0 && c <= MARK_RST7) {
+                restart();
+                m_seq = SEQ_SOS;
+                break;
+            }
+            outputMARK(c);
+            m_seq = SEQ_INIT;
+            break;
+        default:
+            break;
+    }
+}
+
+void BaseJpegDecode::inputScan(uint8_t c)
+{
+    m_bitpat += c;
+    while(m_bitpat.size() > 0) {
+        int tc = (m_scan == 0) ? HT_DC : HT_AC;
+        int th = (m_block < m_yblocks) ? 0 : 1;
+        DBG("%d %d %08x %d\n", tc, th, m_bitpat.peek(32), m_bitpat.size());
+        if (m_huff == NULL) {
+            m_huff = pHD->Lookup(tc, th, &m_bitpat);
+            if (m_huff == NULL) {
+                break;
+            }
+            m_bitpat.get(m_huff->code_size); // skip code
+        }
+        if (m_huff->value_size > m_bitpat.size()) {
+            break;
+        }
+        DBG("%d %d %d %02x\n", m_huff->run, m_huff->value_size, m_huff->code_size, m_huff->code);
+        int value = pHD->getValue(m_huff, &m_bitpat);
+        if (tc == HT_DC) {
+            value += m_old_DC_value[th];
+            outputDC(m_mcu, m_block, value);
+            m_old_DC_value[th] = value;
+            m_scan++;
+            REPORT_CODE(report_scan_dc_count++);
+        } else { // AC
+            if (m_huff->value_size == 0 && m_huff->run == 0) { // EOB
+                DBG("AC EOB\n");
+                m_scan = 64;
+            } else {
+                for(int i = 0; i < m_huff->run; i++) {
+                    outputAC(m_mcu, m_block, m_scan, 0);
+                    m_scan++;
+                }
+                outputAC(m_mcu, m_block, m_scan, value);
+                m_scan++;
+            }
+            if (m_scan >= 64) {
+                m_scan = 0;
+                if (++m_block >= (m_yblocks+2)) {
+                    m_block = 0;
+                    m_mcu++;
+                }
+            }
+            REPORT_CODE(report_scan_ac_count++);
+        }
+        m_huff = NULL;
+        REPORT_CODE(report_scan_count++);
+    }
+}
--- a/BaseJpegDecode.h	Mon Oct 22 13:55:09 2012 +0000
+++ b/BaseJpegDecode.h	Thu Oct 25 11:00:05 2012 +0000
@@ -4,7 +4,6 @@
 #include "HuffmanDecode.h"
 #include "BitPattern.h"
 
-
 class BaseJpegDecode {
 public:
     BaseJpegDecode();
@@ -14,7 +13,18 @@
     virtual void outputDC(int mcu, int block, int value) = 0;
     virtual void outputAC(int mcu, int block, int scan, int value) = 0;
     virtual void outputMARK(uint8_t c) = 0;
+    uint8_t* qt[2];
+    int width;
+    int height;
+    int m_yblocks;
+#ifdef JPEG_USE_REPORT_CODE
+    int report_scan_count;
+    int report_scan_dc_count;
+    int report_scan_ac_count;
+#endif //JPEG_USE_REPORT
 private:
+    void inputDQT(uint8_t c, int pos, int len);
+    void inputSOF(uint8_t c, int pos, int len);
     void inputScan(uint8_t c);
     void restart();
 protected:
@@ -25,9 +35,10 @@
     Huff* m_huff;
     int m_old_DC_value[2];
     BitPattern m_bitpat;
-    int m_skip;
     uint8_t m_mark;
     HuffmanDecode* pHD;
-    int m_yblocks;
+    int m_seg_pos;
+    int m_seg_len;
+    int m_param1;
 };
 #endif // BASE_JPEG_DECODE_H
--- a/bjd_config.h	Mon Oct 22 13:55:09 2012 +0000
+++ b/bjd_config.h	Thu Oct 25 11:00:05 2012 +0000
@@ -2,6 +2,8 @@
 #define BJE_CONFIG_H
 
 #define JPEG_MCU_YBLOCKS 2
+        
 #define JPEG_USE_HUFFMAN_TABLE
+#define JPEG_USE_REPORT_CODE
 
 #endif // BJE_CONFIG_H