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