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:
Wed Dec 05 12:38:56 2012 +0000
Revision:
4:e243fa781e5c
Parent:
3:a7547692071d
Child:
5:85e99ec2e7b5
bug fix

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 4:e243fa781e5c 12 #if 0
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 3:a7547692071d 48 yblock = JPEG_MCU_YBLOCK; // 2 or 4
va009039 1:bfbc18000cca 49 clear();
va009039 1:bfbc18000cca 50 pHD = new HuffmanDecode;
va009039 1:bfbc18000cca 51 DBG_ASSERT(pHD);
va009039 4:e243fa781e5c 52 if (pHD == NULL) {
va009039 4:e243fa781e5c 53 return;
va009039 4:e243fa781e5c 54 }
va009039 1:bfbc18000cca 55 qt[0] = new uint8_t[64];
va009039 1:bfbc18000cca 56 qt[1] = new uint8_t[64];
va009039 1:bfbc18000cca 57 DBG_ASSERT(qt[0]);
va009039 1:bfbc18000cca 58 DBG_ASSERT(qt[1]);
va009039 1:bfbc18000cca 59 }
va009039 1:bfbc18000cca 60
va009039 1:bfbc18000cca 61 void BaseJpegDecode::clear()
va009039 1:bfbc18000cca 62 {
va009039 1:bfbc18000cca 63 m_seq = SEQ_INIT;
va009039 1:bfbc18000cca 64 }
va009039 1:bfbc18000cca 65
va009039 1:bfbc18000cca 66 void BaseJpegDecode::input(uint8_t* buf, int len)
va009039 1:bfbc18000cca 67 {
va009039 1:bfbc18000cca 68 for(int i = 0; i < len; i++) {
va009039 1:bfbc18000cca 69 input(buf[i]);
va009039 1:bfbc18000cca 70 }
va009039 1:bfbc18000cca 71 }
va009039 1:bfbc18000cca 72
va009039 1:bfbc18000cca 73 void BaseJpegDecode::restart()
va009039 1:bfbc18000cca 74 {
va009039 1:bfbc18000cca 75 m_block = 0;
va009039 1:bfbc18000cca 76 m_scan = 0;
va009039 2:5b1dd4e34857 77 m_pre_DC_value[0] = 0;
va009039 2:5b1dd4e34857 78 m_pre_DC_value[1] = 0;
va009039 2:5b1dd4e34857 79 m_pre_DC_value[2] = 0;
va009039 1:bfbc18000cca 80 m_bitpat.clear();
va009039 1:bfbc18000cca 81 m_huff = NULL;
va009039 1:bfbc18000cca 82 }
va009039 1:bfbc18000cca 83
va009039 1:bfbc18000cca 84 void BaseJpegDecode::inputDQT(uint8_t c, int pos, int len)
va009039 1:bfbc18000cca 85 {
va009039 1:bfbc18000cca 86 if (pos == 0 || pos == 65) {
va009039 1:bfbc18000cca 87 m_param1 = c;
va009039 1:bfbc18000cca 88 DBG_ASSERT(m_param1 == 0 || m_param1 == 1);
va009039 1:bfbc18000cca 89 } else {
va009039 4:e243fa781e5c 90 if (m_param1 == 0 || m_param1 == 1) {
va009039 4:e243fa781e5c 91 if(qt[m_param1]) {
va009039 4:e243fa781e5c 92 qt[m_param1][(pos%65)-1] = c;
va009039 4:e243fa781e5c 93 }
va009039 4:e243fa781e5c 94 }
va009039 1:bfbc18000cca 95 }
va009039 1:bfbc18000cca 96 }
va009039 1:bfbc18000cca 97
va009039 1:bfbc18000cca 98 void BaseJpegDecode::inputSOF(uint8_t c, int pos, int len)
va009039 1:bfbc18000cca 99 {
va009039 1:bfbc18000cca 100 switch(pos) {
va009039 1:bfbc18000cca 101 case 1:
va009039 3:a7547692071d 102 height = (height&0x00ff) | (c<<8);
va009039 1:bfbc18000cca 103 break;
va009039 1:bfbc18000cca 104 case 2:
va009039 3:a7547692071d 105 height = (height&0xff00) | c;
va009039 3:a7547692071d 106 break;
va009039 3:a7547692071d 107 case 3:
va009039 3:a7547692071d 108 width = (width&0x00ff) | (c<<8);
va009039 1:bfbc18000cca 109 break;
va009039 1:bfbc18000cca 110 case 4:
va009039 3:a7547692071d 111 width = (width&0xff00) | c;
va009039 1:bfbc18000cca 112 break;
va009039 1:bfbc18000cca 113 case 7:
va009039 1:bfbc18000cca 114 if (c == 0x22) {
va009039 3:a7547692071d 115 yblock = 4;
va009039 1:bfbc18000cca 116 } else if (c == 0x21) {
va009039 3:a7547692071d 117 yblock = 2;
va009039 1:bfbc18000cca 118 } else {
va009039 1:bfbc18000cca 119 DBG_ASSERT(c == 0x22 || c == 0x21);
va009039 1:bfbc18000cca 120 }
va009039 1:bfbc18000cca 121 break;
va009039 1:bfbc18000cca 122 }
va009039 1:bfbc18000cca 123 }
va009039 1:bfbc18000cca 124
va009039 1:bfbc18000cca 125 void BaseJpegDecode::input(uint8_t c)
va009039 1:bfbc18000cca 126 {
va009039 1:bfbc18000cca 127 switch(m_seq) {
va009039 1:bfbc18000cca 128 case SEQ_INIT:
va009039 1:bfbc18000cca 129 if (c == 0xff) {
va009039 1:bfbc18000cca 130 m_seq = SEQ_MARK;
va009039 1:bfbc18000cca 131 }
va009039 1:bfbc18000cca 132 break;
va009039 1:bfbc18000cca 133 case SEQ_MARK:
va009039 1:bfbc18000cca 134 outputMARK(c);
va009039 1:bfbc18000cca 135 if (c == MARK_SOI || c == MARK_EOI) {
va009039 1:bfbc18000cca 136 m_seq = SEQ_INIT;
va009039 1:bfbc18000cca 137 break;
va009039 1:bfbc18000cca 138 }
va009039 1:bfbc18000cca 139 m_mark = c;
va009039 1:bfbc18000cca 140 m_seq = SEQ_SEG_LEN;
va009039 1:bfbc18000cca 141 break;
va009039 1:bfbc18000cca 142 case SEQ_SEG_LEN:
va009039 1:bfbc18000cca 143 m_seg_len = c;
va009039 1:bfbc18000cca 144 m_seq = SEQ_SEG_LEN2;
va009039 1:bfbc18000cca 145 break;
va009039 1:bfbc18000cca 146 case SEQ_SEG_LEN2:
va009039 1:bfbc18000cca 147 m_seg_len <<= 8;
va009039 1:bfbc18000cca 148 m_seg_len |= c;
va009039 1:bfbc18000cca 149 m_seg_len -= 2;
va009039 1:bfbc18000cca 150 m_seg_pos = 0;
va009039 1:bfbc18000cca 151 m_seq = SEQ_SEG_BODY;
va009039 1:bfbc18000cca 152 break;
va009039 1:bfbc18000cca 153 case SEQ_SEG_BODY:
va009039 1:bfbc18000cca 154 if (m_mark == MARK_DQT) {
va009039 1:bfbc18000cca 155 inputDQT(c, m_seg_pos, m_seg_len);
va009039 1:bfbc18000cca 156 } else if (m_mark == MARK_SOF0) {
va009039 1:bfbc18000cca 157 inputSOF(c, m_seg_pos, m_seg_len);
va009039 1:bfbc18000cca 158 }
va009039 1:bfbc18000cca 159 if (++m_seg_pos < m_seg_len) {
va009039 1:bfbc18000cca 160 break;
va009039 1:bfbc18000cca 161 }
va009039 1:bfbc18000cca 162 if (m_mark == MARK_SOS) {
va009039 1:bfbc18000cca 163 m_seq = SEQ_SOS;
va009039 1:bfbc18000cca 164 m_mcu = 0;
va009039 1:bfbc18000cca 165 restart();
va009039 1:bfbc18000cca 166 break;
va009039 1:bfbc18000cca 167 }
va009039 1:bfbc18000cca 168 m_seq = SEQ_INIT;
va009039 1:bfbc18000cca 169 break;
va009039 1:bfbc18000cca 170 case SEQ_SOS:
va009039 1:bfbc18000cca 171 if (c == 0xff) {
va009039 1:bfbc18000cca 172 m_seq = SEQ_SOS2;
va009039 1:bfbc18000cca 173 break;
va009039 1:bfbc18000cca 174 }
va009039 1:bfbc18000cca 175 inputScan(c);
va009039 1:bfbc18000cca 176 break;
va009039 1:bfbc18000cca 177 case SEQ_SOS2:
va009039 1:bfbc18000cca 178 if (c == 0x00) {
va009039 1:bfbc18000cca 179 inputScan(0xff);
va009039 1:bfbc18000cca 180 m_seq = SEQ_SOS;
va009039 1:bfbc18000cca 181 break;
va009039 1:bfbc18000cca 182 } else if (c >= MARK_RST0 && c <= MARK_RST7) {
va009039 1:bfbc18000cca 183 restart();
va009039 1:bfbc18000cca 184 m_seq = SEQ_SOS;
va009039 1:bfbc18000cca 185 break;
va009039 1:bfbc18000cca 186 }
va009039 1:bfbc18000cca 187 outputMARK(c);
va009039 1:bfbc18000cca 188 m_seq = SEQ_INIT;
va009039 1:bfbc18000cca 189 break;
va009039 1:bfbc18000cca 190 default:
va009039 1:bfbc18000cca 191 break;
va009039 1:bfbc18000cca 192 }
va009039 1:bfbc18000cca 193 }
va009039 1:bfbc18000cca 194
va009039 1:bfbc18000cca 195 void BaseJpegDecode::inputScan(uint8_t c)
va009039 1:bfbc18000cca 196 {
va009039 1:bfbc18000cca 197 m_bitpat += c;
va009039 1:bfbc18000cca 198 while(m_bitpat.size() > 0) {
va009039 1:bfbc18000cca 199 int tc = (m_scan == 0) ? HT_DC : HT_AC;
va009039 3:a7547692071d 200 int th = (m_block < yblock) ? 0 : 1;
va009039 1:bfbc18000cca 201 DBG("%d %d %08x %d\n", tc, th, m_bitpat.peek(32), m_bitpat.size());
va009039 1:bfbc18000cca 202 if (m_huff == NULL) {
va009039 1:bfbc18000cca 203 m_huff = pHD->Lookup(tc, th, &m_bitpat);
va009039 1:bfbc18000cca 204 if (m_huff == NULL) {
va009039 1:bfbc18000cca 205 break;
va009039 1:bfbc18000cca 206 }
va009039 1:bfbc18000cca 207 m_bitpat.get(m_huff->code_size); // skip code
va009039 1:bfbc18000cca 208 }
va009039 1:bfbc18000cca 209 if (m_huff->value_size > m_bitpat.size()) {
va009039 1:bfbc18000cca 210 break;
va009039 1:bfbc18000cca 211 }
va009039 1:bfbc18000cca 212 DBG("%d %d %d %02x\n", m_huff->run, m_huff->value_size, m_huff->code_size, m_huff->code);
va009039 1:bfbc18000cca 213 int value = pHD->getValue(m_huff, &m_bitpat);
va009039 1:bfbc18000cca 214 if (tc == HT_DC) {
va009039 2:5b1dd4e34857 215 int sc = 0; // Y
va009039 3:a7547692071d 216 if (m_block == yblock) {
va009039 2:5b1dd4e34857 217 sc = 1; // Cb
va009039 3:a7547692071d 218 } else if (m_block == (yblock+1)) {
va009039 2:5b1dd4e34857 219 sc = 2; // Cr
va009039 2:5b1dd4e34857 220 }
va009039 2:5b1dd4e34857 221 value += m_pre_DC_value[sc];
va009039 1:bfbc18000cca 222 outputDC(m_mcu, m_block, value);
va009039 2:5b1dd4e34857 223 m_pre_DC_value[sc] = value;
va009039 1:bfbc18000cca 224 m_scan++;
va009039 1:bfbc18000cca 225 REPORT_CODE(report_scan_dc_count++);
va009039 1:bfbc18000cca 226 } else { // AC
va009039 1:bfbc18000cca 227 if (m_huff->value_size == 0 && m_huff->run == 0) { // EOB
va009039 1:bfbc18000cca 228 DBG("AC EOB\n");
va009039 2:5b1dd4e34857 229 outputAC(m_mcu, m_block, 63, 0);
va009039 1:bfbc18000cca 230 m_scan = 64;
va009039 1:bfbc18000cca 231 } else {
va009039 1:bfbc18000cca 232 for(int i = 0; i < m_huff->run; i++) {
va009039 2:5b1dd4e34857 233 //outputAC(m_mcu, m_block, m_scan, 0);
va009039 1:bfbc18000cca 234 m_scan++;
va009039 1:bfbc18000cca 235 }
va009039 1:bfbc18000cca 236 outputAC(m_mcu, m_block, m_scan, value);
va009039 1:bfbc18000cca 237 m_scan++;
va009039 1:bfbc18000cca 238 }
va009039 1:bfbc18000cca 239 if (m_scan >= 64) {
va009039 1:bfbc18000cca 240 m_scan = 0;
va009039 3:a7547692071d 241 if (++m_block >= (yblock+2)) {
va009039 1:bfbc18000cca 242 m_block = 0;
va009039 1:bfbc18000cca 243 m_mcu++;
va009039 1:bfbc18000cca 244 }
va009039 1:bfbc18000cca 245 }
va009039 1:bfbc18000cca 246 REPORT_CODE(report_scan_ac_count++);
va009039 1:bfbc18000cca 247 }
va009039 1:bfbc18000cca 248 m_huff = NULL;
va009039 1:bfbc18000cca 249 REPORT_CODE(report_scan_count++);
va009039 1:bfbc18000cca 250 }
va009039 1:bfbc18000cca 251 }