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

Committer:
va009039
Date:
Tue Oct 30 13:22:08 2012 +0000
Revision:
2:5b1dd4e34857
Parent:
1:bfbc18000cca
Child:
3:a7547692071d
add inverseDCT

Who changed what in which revision?

UserRevisionLine numberNew contents of line
va009039 1:bfbc18000cca 1 #include "mbed.h"
va009039 1:bfbc18000cca 2 #include "BaseJpegDecode.h"
va009039 1:bfbc18000cca 3
va009039 1:bfbc18000cca 4 #if 0
va009039 1:bfbc18000cca 5 #define DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);} while(0);
va009039 1:bfbc18000cca 6 #define DBG_WAIT(A) wait_ms(A)
va009039 1:bfbc18000cca 7 #else
va009039 1:bfbc18000cca 8 #define DBG(...)
va009039 1:bfbc18000cca 9 #define DBG_WAIT(A)
va009039 1:bfbc18000cca 10 #endif
va009039 1:bfbc18000cca 11
va009039 1:bfbc18000cca 12 #if 1
va009039 1:bfbc18000cca 13 #define DBG_ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);};
va009039 1:bfbc18000cca 14 #else
va009039 1:bfbc18000cca 15 #define DBG_ASSERT(A)
va009039 1:bfbc18000cca 16 #endif
va009039 1:bfbc18000cca 17
va009039 1:bfbc18000cca 18 #ifdef JPEG_USE_REPORT_CODE
va009039 1:bfbc18000cca 19 #define REPORT_CODE(A) (A)
va009039 1:bfbc18000cca 20 #else
va009039 1:bfbc18000cca 21 #define REPORT_CODE(A)
va009039 1:bfbc18000cca 22 #endif
va009039 1:bfbc18000cca 23
va009039 1:bfbc18000cca 24 #define MARK_SOF0 0xc0
va009039 1:bfbc18000cca 25 #define MARK_DHT 0xc4
va009039 1:bfbc18000cca 26 #define MARK_RST0 0xd0
va009039 1:bfbc18000cca 27 #define MARK_RST7 0xd7
va009039 1:bfbc18000cca 28 #define MARK_SOI 0xd8
va009039 1:bfbc18000cca 29 #define MARK_EOI 0xd9
va009039 1:bfbc18000cca 30 #define MARK_SOS 0xda
va009039 1:bfbc18000cca 31 #define MARK_DQT 0xdb
va009039 1:bfbc18000cca 32 #define MARK_DRI 0xdd
va009039 1:bfbc18000cca 33 #define MARK_APP 0xe0
va009039 1:bfbc18000cca 34
va009039 1:bfbc18000cca 35 #define SEQ_INIT 0
va009039 1:bfbc18000cca 36 #define SEQ_MARK 1
va009039 1:bfbc18000cca 37 #define SEQ_SEG_LEN 2
va009039 1:bfbc18000cca 38 #define SEQ_SEG_LEN2 3
va009039 1:bfbc18000cca 39 #define SEQ_SEG_BODY 4
va009039 1:bfbc18000cca 40 #define SEQ_SOS 5
va009039 1:bfbc18000cca 41 #define SEQ_SOS2 6
va009039 1:bfbc18000cca 42
va009039 1:bfbc18000cca 43 #define HT_DC 0
va009039 1:bfbc18000cca 44 #define HT_AC 1
va009039 1:bfbc18000cca 45
va009039 1:bfbc18000cca 46 BaseJpegDecode::BaseJpegDecode()
va009039 1:bfbc18000cca 47 {
va009039 1:bfbc18000cca 48 m_yblocks = JPEG_MCU_YBLOCKS; // 2 or 4
va009039 1:bfbc18000cca 49 clear();
va009039 1:bfbc18000cca 50 pHD = new HuffmanDecode;
va009039 1:bfbc18000cca 51 DBG_ASSERT(pHD);
va009039 1:bfbc18000cca 52 qt[0] = new uint8_t[64];
va009039 1:bfbc18000cca 53 qt[1] = new uint8_t[64];
va009039 1:bfbc18000cca 54 DBG_ASSERT(qt[0]);
va009039 1:bfbc18000cca 55 DBG_ASSERT(qt[1]);
va009039 1:bfbc18000cca 56 }
va009039 1:bfbc18000cca 57
va009039 1:bfbc18000cca 58 void BaseJpegDecode::clear()
va009039 1:bfbc18000cca 59 {
va009039 1:bfbc18000cca 60 m_seq = SEQ_INIT;
va009039 1:bfbc18000cca 61 }
va009039 1:bfbc18000cca 62
va009039 1:bfbc18000cca 63 void BaseJpegDecode::input(uint8_t* buf, int len)
va009039 1:bfbc18000cca 64 {
va009039 1:bfbc18000cca 65 for(int i = 0; i < len; i++) {
va009039 1:bfbc18000cca 66 input(buf[i]);
va009039 1:bfbc18000cca 67 }
va009039 1:bfbc18000cca 68 }
va009039 1:bfbc18000cca 69
va009039 1:bfbc18000cca 70 void BaseJpegDecode::restart()
va009039 1:bfbc18000cca 71 {
va009039 1:bfbc18000cca 72 m_block = 0;
va009039 1:bfbc18000cca 73 m_scan = 0;
va009039 2:5b1dd4e34857 74 m_pre_DC_value[0] = 0;
va009039 2:5b1dd4e34857 75 m_pre_DC_value[1] = 0;
va009039 2:5b1dd4e34857 76 m_pre_DC_value[2] = 0;
va009039 1:bfbc18000cca 77 m_bitpat.clear();
va009039 1:bfbc18000cca 78 m_huff = NULL;
va009039 1:bfbc18000cca 79 }
va009039 1:bfbc18000cca 80
va009039 1:bfbc18000cca 81 void BaseJpegDecode::inputDQT(uint8_t c, int pos, int len)
va009039 1:bfbc18000cca 82 {
va009039 1:bfbc18000cca 83 if (pos == 0 || pos == 65) {
va009039 1:bfbc18000cca 84 m_param1 = c;
va009039 1:bfbc18000cca 85 DBG_ASSERT(m_param1 == 0 || m_param1 == 1);
va009039 1:bfbc18000cca 86 } else {
va009039 1:bfbc18000cca 87 qt[m_param1][(pos%65)-1] = c;
va009039 1:bfbc18000cca 88 }
va009039 1:bfbc18000cca 89 }
va009039 1:bfbc18000cca 90
va009039 1:bfbc18000cca 91 void BaseJpegDecode::inputSOF(uint8_t c, int pos, int len)
va009039 1:bfbc18000cca 92 {
va009039 1:bfbc18000cca 93 switch(pos) {
va009039 1:bfbc18000cca 94 case 1:
va009039 1:bfbc18000cca 95 case 3:
va009039 1:bfbc18000cca 96 m_param1 = c<<8;
va009039 1:bfbc18000cca 97 break;
va009039 1:bfbc18000cca 98 case 2:
va009039 2:5b1dd4e34857 99 height = m_param1 | c;
va009039 1:bfbc18000cca 100 break;
va009039 1:bfbc18000cca 101 case 4:
va009039 2:5b1dd4e34857 102 width = m_param1 | c;
va009039 1:bfbc18000cca 103 break;
va009039 1:bfbc18000cca 104 case 7:
va009039 1:bfbc18000cca 105 if (c == 0x22) {
va009039 1:bfbc18000cca 106 m_yblocks = 4;
va009039 1:bfbc18000cca 107 } else if (c == 0x21) {
va009039 1:bfbc18000cca 108 m_yblocks = 2;
va009039 1:bfbc18000cca 109 } else {
va009039 1:bfbc18000cca 110 DBG_ASSERT(c == 0x22 || c == 0x21);
va009039 1:bfbc18000cca 111 }
va009039 1:bfbc18000cca 112 break;
va009039 1:bfbc18000cca 113 }
va009039 1:bfbc18000cca 114 }
va009039 1:bfbc18000cca 115
va009039 1:bfbc18000cca 116 void BaseJpegDecode::input(uint8_t c)
va009039 1:bfbc18000cca 117 {
va009039 1:bfbc18000cca 118 switch(m_seq) {
va009039 1:bfbc18000cca 119 case SEQ_INIT:
va009039 1:bfbc18000cca 120 if (c == 0xff) {
va009039 1:bfbc18000cca 121 m_seq = SEQ_MARK;
va009039 1:bfbc18000cca 122 }
va009039 1:bfbc18000cca 123 break;
va009039 1:bfbc18000cca 124 case SEQ_MARK:
va009039 1:bfbc18000cca 125 outputMARK(c);
va009039 1:bfbc18000cca 126 if (c == MARK_SOI || c == MARK_EOI) {
va009039 1:bfbc18000cca 127 m_seq = SEQ_INIT;
va009039 1:bfbc18000cca 128 break;
va009039 1:bfbc18000cca 129 }
va009039 1:bfbc18000cca 130 m_mark = c;
va009039 1:bfbc18000cca 131 m_seq = SEQ_SEG_LEN;
va009039 1:bfbc18000cca 132 break;
va009039 1:bfbc18000cca 133 case SEQ_SEG_LEN:
va009039 1:bfbc18000cca 134 m_seg_len = c;
va009039 1:bfbc18000cca 135 m_seq = SEQ_SEG_LEN2;
va009039 1:bfbc18000cca 136 break;
va009039 1:bfbc18000cca 137 case SEQ_SEG_LEN2:
va009039 1:bfbc18000cca 138 m_seg_len <<= 8;
va009039 1:bfbc18000cca 139 m_seg_len |= c;
va009039 1:bfbc18000cca 140 m_seg_len -= 2;
va009039 1:bfbc18000cca 141 m_seg_pos = 0;
va009039 1:bfbc18000cca 142 m_seq = SEQ_SEG_BODY;
va009039 1:bfbc18000cca 143 break;
va009039 1:bfbc18000cca 144 case SEQ_SEG_BODY:
va009039 1:bfbc18000cca 145 if (m_mark == MARK_DQT) {
va009039 1:bfbc18000cca 146 inputDQT(c, m_seg_pos, m_seg_len);
va009039 1:bfbc18000cca 147 } else if (m_mark == MARK_SOF0) {
va009039 1:bfbc18000cca 148 inputSOF(c, m_seg_pos, m_seg_len);
va009039 1:bfbc18000cca 149 }
va009039 1:bfbc18000cca 150 if (++m_seg_pos < m_seg_len) {
va009039 1:bfbc18000cca 151 break;
va009039 1:bfbc18000cca 152 }
va009039 1:bfbc18000cca 153 if (m_mark == MARK_SOS) {
va009039 1:bfbc18000cca 154 m_seq = SEQ_SOS;
va009039 1:bfbc18000cca 155 m_mcu = 0;
va009039 1:bfbc18000cca 156 restart();
va009039 1:bfbc18000cca 157 break;
va009039 1:bfbc18000cca 158 }
va009039 1:bfbc18000cca 159 m_seq = SEQ_INIT;
va009039 1:bfbc18000cca 160 break;
va009039 1:bfbc18000cca 161 case SEQ_SOS:
va009039 1:bfbc18000cca 162 if (c == 0xff) {
va009039 1:bfbc18000cca 163 m_seq = SEQ_SOS2;
va009039 1:bfbc18000cca 164 break;
va009039 1:bfbc18000cca 165 }
va009039 1:bfbc18000cca 166 inputScan(c);
va009039 1:bfbc18000cca 167 break;
va009039 1:bfbc18000cca 168 case SEQ_SOS2:
va009039 1:bfbc18000cca 169 if (c == 0x00) {
va009039 1:bfbc18000cca 170 inputScan(0xff);
va009039 1:bfbc18000cca 171 m_seq = SEQ_SOS;
va009039 1:bfbc18000cca 172 break;
va009039 1:bfbc18000cca 173 } else if (c >= MARK_RST0 && c <= MARK_RST7) {
va009039 1:bfbc18000cca 174 restart();
va009039 1:bfbc18000cca 175 m_seq = SEQ_SOS;
va009039 1:bfbc18000cca 176 break;
va009039 1:bfbc18000cca 177 }
va009039 1:bfbc18000cca 178 outputMARK(c);
va009039 1:bfbc18000cca 179 m_seq = SEQ_INIT;
va009039 1:bfbc18000cca 180 break;
va009039 1:bfbc18000cca 181 default:
va009039 1:bfbc18000cca 182 break;
va009039 1:bfbc18000cca 183 }
va009039 1:bfbc18000cca 184 }
va009039 1:bfbc18000cca 185
va009039 1:bfbc18000cca 186 void BaseJpegDecode::inputScan(uint8_t c)
va009039 1:bfbc18000cca 187 {
va009039 1:bfbc18000cca 188 m_bitpat += c;
va009039 1:bfbc18000cca 189 while(m_bitpat.size() > 0) {
va009039 1:bfbc18000cca 190 int tc = (m_scan == 0) ? HT_DC : HT_AC;
va009039 1:bfbc18000cca 191 int th = (m_block < m_yblocks) ? 0 : 1;
va009039 1:bfbc18000cca 192 DBG("%d %d %08x %d\n", tc, th, m_bitpat.peek(32), m_bitpat.size());
va009039 1:bfbc18000cca 193 if (m_huff == NULL) {
va009039 1:bfbc18000cca 194 m_huff = pHD->Lookup(tc, th, &m_bitpat);
va009039 1:bfbc18000cca 195 if (m_huff == NULL) {
va009039 1:bfbc18000cca 196 break;
va009039 1:bfbc18000cca 197 }
va009039 1:bfbc18000cca 198 m_bitpat.get(m_huff->code_size); // skip code
va009039 1:bfbc18000cca 199 }
va009039 1:bfbc18000cca 200 if (m_huff->value_size > m_bitpat.size()) {
va009039 1:bfbc18000cca 201 break;
va009039 1:bfbc18000cca 202 }
va009039 1:bfbc18000cca 203 DBG("%d %d %d %02x\n", m_huff->run, m_huff->value_size, m_huff->code_size, m_huff->code);
va009039 1:bfbc18000cca 204 int value = pHD->getValue(m_huff, &m_bitpat);
va009039 1:bfbc18000cca 205 if (tc == HT_DC) {
va009039 2:5b1dd4e34857 206 int sc = 0; // Y
va009039 2:5b1dd4e34857 207 if (m_block == m_yblocks) {
va009039 2:5b1dd4e34857 208 sc = 1; // Cb
va009039 2:5b1dd4e34857 209 } else if (m_block == (m_yblocks+1)) {
va009039 2:5b1dd4e34857 210 sc = 2; // Cr
va009039 2:5b1dd4e34857 211 }
va009039 2:5b1dd4e34857 212 value += m_pre_DC_value[sc];
va009039 1:bfbc18000cca 213 outputDC(m_mcu, m_block, value);
va009039 2:5b1dd4e34857 214 m_pre_DC_value[sc] = value;
va009039 1:bfbc18000cca 215 m_scan++;
va009039 1:bfbc18000cca 216 REPORT_CODE(report_scan_dc_count++);
va009039 1:bfbc18000cca 217 } else { // AC
va009039 1:bfbc18000cca 218 if (m_huff->value_size == 0 && m_huff->run == 0) { // EOB
va009039 1:bfbc18000cca 219 DBG("AC EOB\n");
va009039 2:5b1dd4e34857 220 outputAC(m_mcu, m_block, 63, 0);
va009039 1:bfbc18000cca 221 m_scan = 64;
va009039 1:bfbc18000cca 222 } else {
va009039 1:bfbc18000cca 223 for(int i = 0; i < m_huff->run; i++) {
va009039 2:5b1dd4e34857 224 //outputAC(m_mcu, m_block, m_scan, 0);
va009039 1:bfbc18000cca 225 m_scan++;
va009039 1:bfbc18000cca 226 }
va009039 1:bfbc18000cca 227 outputAC(m_mcu, m_block, m_scan, value);
va009039 1:bfbc18000cca 228 m_scan++;
va009039 1:bfbc18000cca 229 }
va009039 1:bfbc18000cca 230 if (m_scan >= 64) {
va009039 1:bfbc18000cca 231 m_scan = 0;
va009039 1:bfbc18000cca 232 if (++m_block >= (m_yblocks+2)) {
va009039 1:bfbc18000cca 233 m_block = 0;
va009039 1:bfbc18000cca 234 m_mcu++;
va009039 1:bfbc18000cca 235 }
va009039 1:bfbc18000cca 236 }
va009039 1:bfbc18000cca 237 REPORT_CODE(report_scan_ac_count++);
va009039 1:bfbc18000cca 238 }
va009039 1:bfbc18000cca 239 m_huff = NULL;
va009039 1:bfbc18000cca 240 REPORT_CODE(report_scan_count++);
va009039 1:bfbc18000cca 241 }
va009039 1:bfbc18000cca 242 }