jpeg_parser.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  1. /*
  2. * Copyright (c) 2020, Actions Semi Co., Inc.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /**
  7. ******************************************************************************
  8. * @file jpeg_parser.c
  9. * @brief JPEG HAL module driver.
  10. * This file provides firmware functions to manage the following
  11. * functionalities of the JPEG HW decoder peripheral:
  12. * + Initialization and de-initialization functions
  13. * + IO operation functions
  14. * + Peripheral Control functions
  15. * + Peripheral State and Errors functions
  16. *
  17. */
  18. #include <stdint.h>
  19. #include <string.h>
  20. #include <assert.h>
  21. #include <jpeg_parser.h>
  22. const int exiftag = 0x66697845; //'e''x''i''f'
  23. const uint8_t zigzag[64]=
  24. { 0, 1, 8,16, 9, 2, 3,10,
  25. 17,24,32,25,18,11, 4, 5,
  26. 12,19,26,33,40,48,41,34,
  27. 27,20,13, 6, 7,14,21,28,
  28. 35,42,49,56,57,50,43,36,
  29. 29,22,15,23,30,37,44,51,
  30. 58,59,52,45,38,31,39,46,
  31. 53,60,61,54,47,55,62,63
  32. };
  33. int JFREAD(jpeg_parser_info_t *parser_info, void *buf, int len)
  34. {
  35. if (parser_info->jpeg_current_offset + len > parser_info->jpeg_size) {
  36. len = parser_info->jpeg_size - parser_info->jpeg_current_offset;
  37. }
  38. memcpy(buf, &parser_info->jpeg_base[parser_info->jpeg_current_offset], len);
  39. parser_info->jpeg_current_offset += len;
  40. return len;
  41. }
  42. #define JFTELL(parser_info) parser_info->jpeg_current_offset
  43. #define JFOFFSET(parser_info) parser_info->jpeg_current_offset
  44. /**********************************************************
  45. * get one bytes from jpeg
  46. ***********************************************************
  47. **/
  48. static inline uint8_t _jpeg_parser_getbyte(struct jpeg_parser_info *parser_info)
  49. {
  50. uint8_t rval =0;
  51. if (JFREAD(parser_info, &rval, 1) == 0) {
  52. parser_info->nodata = 1;
  53. }
  54. return rval;
  55. }
  56. /**********************************************************
  57. * get two bytes from jpeg
  58. ***********************************************************
  59. **/
  60. static inline int _jpeg_parser_get2bytes(struct jpeg_parser_info *parser_info)
  61. {
  62. int len = (_jpeg_parser_getbyte(parser_info)<<8);
  63. len |= (int)_jpeg_parser_getbyte(parser_info);
  64. return len;
  65. }
  66. static inline int _jpeg_parser_get2bytesL(struct jpeg_parser_info *parser_info)
  67. {
  68. int len = _jpeg_parser_getbyte(parser_info);
  69. len |= (_jpeg_parser_getbyte(parser_info)<<8);
  70. return len;
  71. }
  72. /**********************************************************
  73. * get four bytes from jpeg
  74. ***********************************************************
  75. **/
  76. static inline int _jpeg_parser_get4bytes(struct jpeg_parser_info *parser_info)
  77. {
  78. int len = (_jpeg_parser_getbyte(parser_info) << 24);
  79. len |= (_jpeg_parser_getbyte(parser_info) << 16);
  80. len |= (_jpeg_parser_getbyte(parser_info) << 8);
  81. len |= (int)_jpeg_parser_getbyte(parser_info);
  82. return len;
  83. }
  84. static inline int _jpeg_parser_get4bytesL(struct jpeg_parser_info *parser_info)
  85. {
  86. int len = _jpeg_parser_getbyte(parser_info);
  87. len |= (_jpeg_parser_getbyte(parser_info) << 8);
  88. len |= (_jpeg_parser_getbyte(parser_info) << 16);
  89. len |= (_jpeg_parser_getbyte(parser_info) << 24);
  90. return len;
  91. }
  92. /**********************************************************
  93. * skip len data
  94. ***********************************************************
  95. **/
  96. static int _jpeg_parser_skipbytes(struct jpeg_parser_info *parser_info, uint32_t len)
  97. {
  98. #define TMP_BUF_LEN 128
  99. uint8_t tmpbuf[TMP_BUF_LEN];
  100. int rnum =0;
  101. while(len > 0) {
  102. if (len > TMP_BUF_LEN) {
  103. rnum = JFREAD(parser_info, tmpbuf, TMP_BUF_LEN);
  104. if (rnum != TMP_BUF_LEN) {
  105. parser_info->nodata = 1;
  106. break;
  107. }
  108. len -= TMP_BUF_LEN;
  109. } else {
  110. rnum = JFREAD(parser_info, tmpbuf, len);
  111. if (rnum != len) {
  112. parser_info->nodata = 1;
  113. }
  114. len = 0;
  115. }
  116. }
  117. return 0;
  118. }
  119. static int _jpeg_parser_get_data(struct jpeg_parser_info *parser_info, uint8_t *buf , uint32_t len)
  120. {
  121. int rnum = JFREAD(parser_info, buf, len);
  122. if (rnum != len) {
  123. parser_info->nodata = 1;
  124. }
  125. return rnum;
  126. }
  127. static int _jpeg_parser_mark_skip(struct jpeg_parser_info *parser_info)
  128. {
  129. int section_len = _jpeg_parser_get2bytes(parser_info) - 2;
  130. _jpeg_parser_skipbytes(parser_info, section_len);
  131. return EN_NORMAL;
  132. }
  133. /**********************************************************
  134. * jpeg deal for 0xc0 mark
  135. ***********************************************************
  136. **/
  137. static int _jpeg_parser_sof0(struct jpeg_parser_info *parser_info)
  138. {
  139. struct jpeg_info_t *jpeg_info = &parser_info->jpeg_info;
  140. int sof_len=0;
  141. int i=0;
  142. int w=0;
  143. int h=0;
  144. int Nnum=0;
  145. int HV=0;
  146. int H[3] = {0};
  147. int V[3]= {0};
  148. sof_len = _jpeg_parser_get2bytes(parser_info);
  149. _jpeg_parser_getbyte(parser_info);
  150. //x,y
  151. h = _jpeg_parser_get2bytes(parser_info);
  152. w = _jpeg_parser_get2bytes(parser_info);
  153. Nnum = _jpeg_parser_getbyte(parser_info);
  154. if (Nnum > 3) {
  155. return EN_NOSUPPORT;
  156. }
  157. sof_len -= 8;
  158. for (i = 0; i < Nnum; i++) {
  159. _jpeg_parser_getbyte(parser_info);
  160. HV = _jpeg_parser_getbyte(parser_info);
  161. H[i] = HV >> 4;
  162. V[i] = HV & 0xf;
  163. _jpeg_parser_getbyte(parser_info);
  164. sof_len -= 3;
  165. }
  166. jpeg_info->yuv_mode = YUV_OTHER;
  167. if ((H[0]==1)&&(V[0]==1)&&(Nnum == 1))
  168. {
  169. jpeg_info->yuv_mode = YUV100;
  170. }
  171. if ((H[0]==2)&&(V[0]==2)&&(H[1]==1)&&(V[1]==1)&&(H[2]==1)&&(V[2]==1))
  172. {
  173. jpeg_info->yuv_mode = YUV420;
  174. }
  175. if ((H[0]==2)&&(V[0]==2)&&(H[1]==1)&&(V[1]==2)&&(H[2]==1)&&(V[2]==2))
  176. {
  177. jpeg_info->yuv_mode = YUV422;
  178. }
  179. if ((H[0]==2)&&(V[0]==1)&&(H[1]==1)&&(V[1]==1)&&(H[2]==1)&&(V[2]==1))
  180. {
  181. jpeg_info->yuv_mode = YUV211H;
  182. }
  183. if ((H[0]==1)&&(V[0]==2)&&(H[1]==1)&&(V[1]==1)&&(H[2]==1)&&(V[2]==1))
  184. {
  185. jpeg_info->yuv_mode = YUV211V;
  186. }
  187. if ((H[0]==1)&&(V[0]==1)&&(H[1]==1)&&(V[1]==1)&&(H[2]==1)&&(V[2]==1))
  188. {
  189. jpeg_info->yuv_mode = YUV111;
  190. }
  191. if (sof_len > 0)
  192. {
  193. _jpeg_parser_skipbytes(parser_info, sof_len);
  194. }
  195. jpeg_info->image_w = w;
  196. jpeg_info->image_h = h;
  197. return EN_NORMAL;
  198. }
  199. /**********************************************************
  200. * jpeg deal for 0xe1 mark
  201. ***********************************************************/
  202. static int _jpeg_parser_app1(struct jpeg_parser_info *parser_info)
  203. {
  204. struct jpeg_info_t *jpeg_info = &parser_info->jpeg_info;
  205. int app1_len =0;
  206. int idf_entry=0;
  207. int cur_offset=0;
  208. int idf1_offset=0;
  209. int i=0;
  210. int tag=0;
  211. int start_file_pos=0;
  212. int thumbnail_pos=0;
  213. int DateTimeValueOffset=0;
  214. int byteorder = 0;
  215. int (*get2b)(struct jpeg_parser_info *) = 0;
  216. int (*get4b)(struct jpeg_parser_info *) = 0;
  217. int ifdoffset = 0;
  218. cur_offset = 0;
  219. //len
  220. app1_len = _jpeg_parser_get2bytes(parser_info);
  221. if (app1_len < 6) {
  222. return EN_NORMAL;
  223. }
  224. //exif
  225. tag = _jpeg_parser_get4bytesL(parser_info);
  226. if ((tag != exiftag) || (app1_len <= 8)) {
  227. _jpeg_parser_skipbytes(parser_info, app1_len - 2 - 4);
  228. //printk("tag %x exiftag %x \n",tag,exiftag);
  229. return EN_NORMAL;
  230. }
  231. //00 00
  232. _jpeg_parser_skipbytes(parser_info, 2);
  233. //offset start
  234. start_file_pos = JFTELL(parser_info);
  235. byteorder = _jpeg_parser_get2bytes(parser_info);
  236. if (byteorder == 0x4d4d) {
  237. get2b = _jpeg_parser_get2bytes; //big
  238. get4b = _jpeg_parser_get4bytes;
  239. } else {
  240. get2b = _jpeg_parser_get2bytesL; //little
  241. get4b = _jpeg_parser_get4bytesL;
  242. }
  243. //_jpeg_parser_skipbytes(pjpg, 6);
  244. _jpeg_parser_skipbytes(parser_info, 2);
  245. ifdoffset = get4b(parser_info);
  246. if (ifdoffset != 0x08) {
  247. _jpeg_parser_skipbytes(parser_info, app1_len - 8 - 8);
  248. //printk("ifdoffset %x \n",ifdoffset);
  249. return EN_NORMAL;
  250. }
  251. //IDF0
  252. idf_entry = get2b(parser_info);
  253. for (i = 0;i < idf_entry; i++) {
  254. tag = get2b(parser_info);
  255. if (tag == 0x0132) {
  256. _jpeg_parser_skipbytes(parser_info, 6);
  257. DateTimeValueOffset = get4b(parser_info);
  258. continue;
  259. }
  260. _jpeg_parser_skipbytes(parser_info, 10);
  261. }
  262. cur_offset += 10 + idf_entry * 12;
  263. idf1_offset = get2b(parser_info);
  264. cur_offset += 2;
  265. if (idf1_offset == 0) //some pic have padding???
  266. {
  267. idf1_offset = get2b(parser_info);
  268. cur_offset += 2;
  269. if (idf1_offset == 0) {
  270. _jpeg_parser_skipbytes(parser_info, app1_len - (cur_offset + 8));
  271. //printk("ifdoffset %x \n",idf1_offset);
  272. return EN_NORMAL;
  273. }
  274. }
  275. //IDF1
  276. if ((DateTimeValueOffset == 0) || (DateTimeValueOffset > idf1_offset)) {
  277. _jpeg_parser_skipbytes(parser_info, idf1_offset - cur_offset);
  278. } else {
  279. _jpeg_parser_skipbytes(parser_info, DateTimeValueOffset - cur_offset);
  280. //get time
  281. _jpeg_parser_get_data(parser_info, jpeg_info->Date, 20);
  282. _jpeg_parser_skipbytes(parser_info, idf1_offset - DateTimeValueOffset - 20);
  283. }
  284. cur_offset = idf1_offset;
  285. idf_entry = get2b(parser_info);
  286. for(i = 0;i < idf_entry; i++) {
  287. tag = get2b(parser_info);
  288. if (tag == 0x0201) {
  289. _jpeg_parser_skipbytes(parser_info, 6);
  290. thumbnail_pos = get4b(parser_info);
  291. continue;
  292. }
  293. _jpeg_parser_skipbytes(parser_info, 10);
  294. }
  295. cur_offset += 2 + (idf_entry) * 12;
  296. if (DateTimeValueOffset > idf1_offset) {
  297. _jpeg_parser_skipbytes(parser_info, DateTimeValueOffset - cur_offset);
  298. //get time
  299. _jpeg_parser_get_data(parser_info, jpeg_info->Date, 20);
  300. app1_len -= (DateTimeValueOffset + 20 + 8);
  301. } else {
  302. app1_len -= (idf1_offset + 8);
  303. app1_len -= (2 + (idf_entry)*12);
  304. }
  305. if (app1_len > 0) {
  306. _jpeg_parser_skipbytes(parser_info, app1_len);
  307. }
  308. parser_info->thumbnailoffset = thumbnail_pos + start_file_pos;
  309. //start_file_pos = JFTELL(parser_info);
  310. return EN_NORMAL;
  311. }
  312. /**********************************************************
  313. * jpeg deal for 0xc4 mark
  314. ***********************************************************
  315. **/
  316. static int _jpeg_parser_dht(struct jpeg_parser_info *parser_info)
  317. {
  318. struct jpeg_info_t *jpeg_info = &parser_info->jpeg_info;
  319. uint8_t *curtable=0;
  320. uint8_t *curvaltable=0;
  321. int dht_len=0;
  322. int len=0;
  323. int i=0;
  324. uint8_t tcth=0;
  325. dht_len = _jpeg_parser_get2bytes(parser_info);
  326. dht_len -= 2;
  327. //get len
  328. while(dht_len > 16) {
  329. //len i
  330. tcth = _jpeg_parser_getbyte(parser_info);
  331. if (tcth & 0xf0) {
  332. if (tcth & 0x0f) {
  333. curtable = &jpeg_info->AC_TAB1[0];
  334. curvaltable = (uint8_t*)ACHuf_1;
  335. } else {
  336. curtable = &jpeg_info->AC_TAB0[0];
  337. curvaltable = (uint8_t*)ACHuf_0;
  338. }
  339. } else {
  340. if (tcth & 0x0f) {
  341. curtable = &jpeg_info->DC_TAB1[0];
  342. curvaltable = (uint8_t*)DCHuf_1;
  343. } else {
  344. curtable = &jpeg_info->DC_TAB0[0];
  345. curvaltable = (uint8_t*)DCHuf_0;
  346. }
  347. }
  348. _jpeg_parser_get_data(parser_info, curtable, 16);
  349. len = 0;
  350. for(i = 0;i < 16;i++) {
  351. len += curtable[i];
  352. }
  353. //val i
  354. _jpeg_parser_get_data(parser_info, curvaltable, len);
  355. dht_len -= (len + 17);
  356. }
  357. if (dht_len) {
  358. _jpeg_parser_skipbytes(parser_info, dht_len);
  359. }
  360. #if 0
  361. printk("ACHuf_0 table: \n");
  362. for(i = 0; i < 64; i++){
  363. printk("0x%x ",*(uint8_t *)(ACHuf_0 + i));
  364. }
  365. printk("\n");
  366. printk("ACHuf_1 table: \n");
  367. for(i = 0; i < 64; i++){
  368. printk("0x%x ",*(uint8_t *)(ACHuf_1 + i));
  369. }
  370. printk("\n");
  371. printk("DCHuf_0 table: \n");
  372. for(i = 0; i < 64; i++){
  373. printk("0x%x ",*(uint8_t *)(DCHuf_0 + i));
  374. }
  375. printk("\n");
  376. printk("DCHuf_1 table: \n");
  377. for(i = 0; i < 64; i++){
  378. printk("0x%x ",*(uint8_t *)(DCHuf_1 + i));
  379. }
  380. printk("\n");
  381. #endif
  382. return EN_NORMAL;
  383. }
  384. /*
  385. len: 2bytes
  386. table 0-3
  387. {
  388. tq
  389. V[64] ()
  390. }
  391. */
  392. /**********************************************************
  393. * jpeg deal for 0xdb mark
  394. ***********************************************************
  395. **/
  396. static int _jpeg_parser_dqt(struct jpeg_parser_info *parser_info)
  397. {
  398. struct jpeg_info_t *jpeg_info = &parser_info->jpeg_info;
  399. uint8_t *curtable=0;
  400. int dqt_len=0;
  401. int i=0;
  402. uint8_t tq=0;
  403. dqt_len = _jpeg_parser_get2bytes(parser_info);
  404. dqt_len -= 2;
  405. //get len
  406. while(dqt_len > 16) {
  407. //len i
  408. tq = _jpeg_parser_getbyte(parser_info);
  409. if (tq == 0x0) {
  410. curtable = (uint8_t*)QT_0;
  411. } else if (tq == 0x1) {
  412. curtable = (uint8_t*)QT_1;
  413. } else {
  414. curtable = (uint8_t*)QT_2;
  415. }
  416. //len = 0;
  417. for (i = 0; i < 64; i++) {
  418. curtable[zigzag[i]]= _jpeg_parser_getbyte(parser_info);
  419. }
  420. dqt_len -= 65;
  421. jpeg_info->getQTablenum++;
  422. if (tq == 0x1) {
  423. memcpy((char*)QT_2, (const char*)QT_1, 64);
  424. }
  425. }
  426. if (dqt_len) {
  427. _jpeg_parser_skipbytes(parser_info, dqt_len);
  428. }
  429. #if 0
  430. printk("QT_0 table: tq %d \n",tq);
  431. for(i = 0; i < 64; i++){
  432. printk("0x%x ",*(uint8_t *)(QT_0 + i));
  433. }
  434. printk("\n");
  435. printk("QT_1 table: \n");
  436. for(i = 0; i < 64; i++){
  437. printk("0x%x ",*(uint8_t *)(QT_1 + i));
  438. }
  439. printk("\n");
  440. printk("QT_2 table: \n");
  441. for(i = 0; i < 64; i++){
  442. printk("0x%x ",*(uint8_t *)(QT_2 + i));
  443. }
  444. printk("\n");
  445. #endif
  446. return EN_NORMAL;
  447. }
  448. /**********************************************************
  449. * jpeg deal for 0xda mark
  450. ***********************************************************
  451. **/
  452. static int _jpeg_parser_sos(struct jpeg_parser_info *parser_info)
  453. {
  454. struct jpeg_info_t *jpeg_info = &parser_info->jpeg_info;
  455. int sos_len=0;
  456. int i=0;
  457. unsigned int tmp=0;
  458. unsigned int cIndex=0;
  459. sos_len = _jpeg_parser_get2bytes(parser_info);
  460. sos_len -= 2;
  461. jpeg_info->scan.Ns = _jpeg_parser_getbyte(parser_info);
  462. if (jpeg_info->scan.Ns > 3) {
  463. return EN_NOSUPPORT;
  464. }
  465. if (jpeg_info->scan.Ns == 1) {
  466. tmp = _jpeg_parser_getbyte(parser_info);
  467. cIndex = tmp - 1;
  468. if (cIndex > 2) {
  469. return EN_NOSUPPORT;
  470. }
  471. jpeg_info->scan.Cs[cIndex] = tmp;
  472. tmp = _jpeg_parser_getbyte(parser_info);
  473. jpeg_info->scan.Td[cIndex] = tmp >> 4;
  474. jpeg_info->scan.Ta[cIndex] = tmp & 0x0F;
  475. /* decoding info */
  476. jpeg_info->amountOfQTables = 1;
  477. } else {
  478. for (i = 0; i < jpeg_info->scan.Ns; i++) {
  479. jpeg_info->scan.Cs[i] = _jpeg_parser_getbyte(parser_info);
  480. tmp = _jpeg_parser_getbyte(parser_info);
  481. jpeg_info->scan.Td[i] = tmp >> 4; /* which DC table */
  482. jpeg_info->scan.Ta[i] = tmp & 0x0F; /* which AC table */
  483. }
  484. jpeg_info->amountOfQTables = 3;
  485. }
  486. //ss,se,ahal
  487. _jpeg_parser_skipbytes(parser_info, 3);
  488. if ((jpeg_info->amountOfQTables == 3)&&(jpeg_info->getQTablenum == 1)) {
  489. memcpy((char*)QT_1, (const char*)QT_0, 64);
  490. memcpy((char*)QT_2, (const char*)QT_1, 64);
  491. }
  492. jpeg_info->stream_addr = &parser_info->jpeg_base[parser_info->jpeg_current_offset];
  493. jpeg_info->stream_size = parser_info->jpeg_size - parser_info->jpeg_current_offset;
  494. return EN_NORMAL;
  495. }
  496. /**********************************************************
  497. * get mark from jpeg
  498. ***********************************************************
  499. **/
  500. static int _jpeg_parser_get_mark(struct jpeg_parser_info *parser_info)
  501. {
  502. uint8_t tag=0;
  503. do {
  504. do {
  505. if (parser_info->nodata) {
  506. return M_NODATA;
  507. }
  508. tag = _jpeg_parser_getbyte(parser_info);
  509. } while(tag != 0xff);
  510. while(tag == 0xff) {
  511. if (parser_info->nodata) {
  512. return M_NODATA;
  513. }
  514. tag = _jpeg_parser_getbyte(parser_info);
  515. }
  516. if (tag != 0) {
  517. break;
  518. }
  519. }while(1);
  520. return tag;
  521. }
  522. const jpeg_marker_handle_t jpeg_rout[]=
  523. {
  524. {M_SOF0, _jpeg_parser_sof0},//0xc0
  525. //{M_APP0, _jpeg_parser_app0},//0xe0
  526. {M_APP1, _jpeg_parser_app1},//0xe1
  527. {M_DHT, _jpeg_parser_dht},//0xc4
  528. {M_DQT, _jpeg_parser_dqt},//0xdb
  529. {M_SOS, _jpeg_parser_sos},//0xda
  530. };
  531. /**********************************************************
  532. * parser jpeg info
  533. ***********************************************************
  534. **/
  535. int jpeg_parser_process(struct jpeg_parser_info *parser_info, int mode)
  536. {
  537. jpeg_marker_handle_t *mark_handle = NULL;
  538. uint8_t tag = 0;
  539. int i = 0;
  540. int rts = EN_NORMAL;
  541. for(;;) {
  542. if (parser_info->nodata) {
  543. break;
  544. }
  545. //get mark
  546. tag = _jpeg_parser_get_mark(parser_info);
  547. //printk("tag: %x \n",tag);
  548. switch (tag) {
  549. case M_SOF1: // 0xc1
  550. case M_SOF2: // 0xc2
  551. case M_SOF3: // 0xc3
  552. case M_SOF9: // 0xc9
  553. case M_SOF10: // 0xca
  554. case M_SOF11: // 0xcb
  555. return EN_NOSUPPORT;
  556. //break;
  557. case M_SOI: // 0xd8
  558. continue;
  559. default:
  560. break;
  561. }
  562. mark_handle = NULL;
  563. for (i = 0; i < 5; i++) {
  564. if (tag == jpeg_rout[i].marker) {
  565. mark_handle = (jpeg_marker_handle_t *)&jpeg_rout[i];
  566. }
  567. }
  568. if (mark_handle) {
  569. rts = (rt_status_t)mark_handle->marker_pro((void *)parser_info);
  570. if (rts || (parser_info->thumbnailoffset != 0)) {
  571. return rts;
  572. }
  573. } else {
  574. _jpeg_parser_mark_skip((void *)parser_info);
  575. }
  576. if (tag == M_SOS) {
  577. return 0;
  578. }
  579. }
  580. // da end
  581. return 0;
  582. }