Kyle Post / BaseJpegDecode

Dependents:   Color_Targeting_Catapult

Fork of BaseJpegDecode by Norimasa Okamoto

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers BaseJpegDecode.cpp Source File

BaseJpegDecode.cpp

00001 // BaseJpegDecode.cpp 2013/1/27
00002 #include "mbed.h"
00003 #include "BaseJpegDecode.h"
00004 
00005 #if 0
00006 #define DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);} while(0);
00007 #define DBG_WAIT(A) wait_ms(A)
00008 #else
00009 #define DBG(...)
00010 #define DBG_WAIT(A)
00011 #endif
00012 
00013 #if 0
00014 #define DBG_ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);};
00015 #else
00016 #define DBG_ASSERT(A) 
00017 #endif
00018 
00019 #ifdef JPEG_USE_REPORT_CODE
00020 #define REPORT_CODE(A) (A)
00021 #else
00022 #define REPORT_CODE(A)
00023 #endif
00024 
00025 #define MARK_SOF0 0xc0
00026 #define MARK_DHT  0xc4
00027 #define MARK_RST0 0xd0
00028 #define MARK_RST7 0xd7
00029 #define MARK_SOI  0xd8
00030 #define MARK_EOI  0xd9
00031 #define MARK_SOS  0xda
00032 #define MARK_DQT  0xdb
00033 #define MARK_DRI  0xdd
00034 #define MARK_APP  0xe0
00035 
00036 #define SEQ_INIT     0
00037 #define SEQ_SOI      1
00038 #define SEQ_FRAME    2
00039 #define SEQ_MARK     3
00040 #define SEQ_SEG_LEN  4
00041 #define SEQ_SEG_LEN2 5
00042 #define SEQ_SEG_BODY 6
00043 #define SEQ_SOS      7
00044 #define SEQ_SOS2     8
00045 
00046 #define HT_DC 0
00047 #define HT_AC 1
00048 
00049 BaseJpegDecode::BaseJpegDecode()
00050 {
00051     yblock = JPEG_MCU_YBLOCK; // 2 or 4
00052     clear();
00053     pHD = new HuffmanDecode;
00054     DBG_ASSERT(pHD);
00055     if (pHD == NULL) {
00056         return;
00057     }
00058     qt[0] = new uint8_t[64];
00059     qt[1] = new uint8_t[64];
00060     DBG_ASSERT(qt[0]);
00061     DBG_ASSERT(qt[1]);
00062 }
00063 
00064 void BaseJpegDecode::clear()
00065 {
00066     m_seq = SEQ_INIT;
00067 }
00068 
00069 void BaseJpegDecode::input(uint8_t* buf, int len)
00070 {
00071     for(int i = 0; i < len; i++) {
00072         input(buf[i]);
00073         printf("decode line %i\r\n", i);
00074     }
00075 }
00076 
00077 void BaseJpegDecode::restart()
00078 {
00079     m_block = 0;
00080     m_scan = 0;
00081     m_pre_DC_value[0] = 0;
00082     m_pre_DC_value[1] = 0;
00083     m_pre_DC_value[2] = 0;
00084     m_bitpat.clear();
00085     m_huff = NULL;
00086 }
00087 
00088 void BaseJpegDecode::inputDQT(uint8_t c, int pos, int len)
00089 {
00090     if (pos == 0 || pos == 65) {
00091         m_param1 = c;
00092         DBG_ASSERT(m_param1 == 0 || m_param1 == 1);
00093     } else {
00094         if (m_param1 == 0 || m_param1 == 1) { 
00095             if(qt[m_param1]) {
00096                 qt[m_param1][(pos%65)-1] = c;
00097             }
00098         }
00099     }
00100 }
00101 
00102 void BaseJpegDecode::inputSOF(uint8_t c, int pos, int len)
00103 {
00104     switch(pos) {
00105         case 1:
00106             height = (height&0x00ff) | (c<<8);
00107             break;
00108         case 2:
00109             height = (height&0xff00) | c;
00110             break;
00111         case 3:
00112             width = (width&0x00ff) | (c<<8);
00113             break;
00114         case 4:
00115             width = (width&0xff00) | c;
00116             break;
00117         case 7:
00118             if (c == 0x22) {
00119                 yblock = 4;
00120             } else if (c == 0x21) {
00121                 yblock = 2;
00122             } else {
00123                 DBG_ASSERT(c == 0x22 || c == 0x21);
00124             }
00125             break;
00126     }
00127 }
00128 
00129 void BaseJpegDecode::input(uint8_t c)
00130 {
00131     switch(m_seq) {
00132         case SEQ_INIT:
00133             if (c == 0xff) {
00134                 m_seq = SEQ_SOI;
00135             }
00136             break;
00137         case SEQ_SOI:
00138             if (c == MARK_SOI) {
00139                 outputMARK(c);
00140                 m_seq = SEQ_FRAME;
00141             } else {
00142                 m_seq = SEQ_INIT;
00143             }
00144             break;
00145         case SEQ_FRAME:
00146             if (c == 0xff) {
00147                 m_seq = SEQ_MARK;
00148             } else {
00149                 m_seq = SEQ_INIT;
00150             }
00151             break;
00152         case SEQ_MARK:
00153             outputMARK(c);
00154             if (c == MARK_SOI) {
00155                 m_seq = SEQ_FRAME;
00156                 break;
00157             } else if (c == MARK_EOI || c == 0x00) {
00158                 m_seq = SEQ_INIT;
00159                 break;
00160             }
00161             m_mark = c;
00162             m_seq = SEQ_SEG_LEN;
00163             break;
00164         case SEQ_SEG_LEN:
00165             m_seg_len = c;
00166             m_seq = SEQ_SEG_LEN2;
00167             break;
00168         case SEQ_SEG_LEN2:
00169             m_seg_len <<= 8;
00170             m_seg_len |= c;
00171             m_seg_len -= 2;
00172             m_seg_pos = 0;
00173             m_seq = SEQ_SEG_BODY;
00174             break;
00175         case SEQ_SEG_BODY:
00176             if (m_mark == MARK_DQT) {
00177                 inputDQT(c, m_seg_pos, m_seg_len);
00178             } else if (m_mark == MARK_SOF0) {
00179                 inputSOF(c, m_seg_pos, m_seg_len);
00180             }
00181             if (++m_seg_pos < m_seg_len) {
00182                 break;
00183             }
00184             if (m_mark == MARK_SOS) {
00185                 m_seq = SEQ_SOS;
00186                 m_mcu = 0;
00187                 restart();
00188                 break;
00189             }
00190             m_seq = SEQ_FRAME;
00191             break;
00192         case SEQ_SOS:
00193             if (c == 0xff) {
00194                 m_seq = SEQ_SOS2;
00195                 break;
00196             }
00197             inputScan(c);
00198             break;
00199         case SEQ_SOS2:
00200             if (c == 0x00) {
00201                 inputScan(0xff);
00202                 m_seq = SEQ_SOS;
00203                 break;
00204             } else if (c >= MARK_RST0 && c <= MARK_RST7) {
00205                 restart();
00206                 m_seq = SEQ_SOS;
00207                 break;
00208             }
00209             outputMARK(c);
00210             m_seq = SEQ_INIT;
00211             break;
00212         default:
00213             break;
00214     }
00215 }
00216 
00217 void BaseJpegDecode::inputScan(uint8_t c)
00218 {
00219     m_bitpat += c;
00220     while(m_bitpat.size() > 0) {
00221         int tc = (m_scan == 0) ? HT_DC : HT_AC;
00222         int th = (m_block < yblock) ? 0 : 1;
00223         DBG("%d %d %08x %d\n", tc, th, m_bitpat.peek(32), m_bitpat.size());
00224         if (m_huff == NULL) {
00225             m_huff = pHD->Lookup(tc, th, &m_bitpat);
00226             if (m_huff == NULL) {
00227                 break;
00228             }
00229             m_bitpat.get(m_huff->code_size); // skip code
00230         }
00231         if (m_huff->value_size > m_bitpat.size()) {
00232             break;
00233         }
00234         DBG("%d %d %d %02x\n", m_huff->run, m_huff->value_size, m_huff->code_size, m_huff->code);
00235         int value = pHD->getValue(m_huff, &m_bitpat);
00236         if (tc == HT_DC) {
00237             int sc = 0; // Y
00238             if (m_block == yblock) {
00239                 sc = 1; // Cb
00240             } else if (m_block == (yblock+1)) {
00241                 sc = 2; // Cr
00242             }
00243             value += m_pre_DC_value[sc];
00244             outputDC(m_mcu, m_block, value);
00245             m_pre_DC_value[sc] = value;
00246             m_scan++;
00247             REPORT_CODE(report_scan_dc_count++);
00248         } else { // AC
00249             if (m_huff->value_size == 0 && m_huff->run == 0) { // EOB
00250                 DBG("AC EOB\n");
00251                 outputAC(m_mcu, m_block, 63, 0);
00252                 m_scan = 64;
00253             } else {
00254                 for(int i = 0; i < m_huff->run; i++) {
00255                     //outputAC(m_mcu, m_block, m_scan, 0);
00256                     m_scan++;
00257                 }
00258                 outputAC(m_mcu, m_block, m_scan, value);
00259                 m_scan++;
00260             }
00261             if (m_scan >= 64) {
00262                 m_scan = 0;
00263                 if (++m_block >= (yblock+2)) {
00264                     m_block = 0;
00265                     m_mcu++;
00266                 }
00267             }
00268             REPORT_CODE(report_scan_ac_count++);
00269         }
00270         m_huff = NULL;
00271         REPORT_CODE(report_scan_count++);
00272     }
00273 }