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:
Thu Oct 25 11:00:05 2012 +0000
Revision:
1:bfbc18000cca
Child:
2:5b1dd4e34857
support DQT

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