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:
Sat Feb 02 01:18:15 2013 +0000
Revision:
6:d7ee458cacd1
Parent:
5:85e99ec2e7b5
aanIDCT add range_limit()

Who changed what in which revision?

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