2025-07-06 17:11:38 +08:00
|
|
|
|
#include "mjpeg.h"
|
|
|
|
|
#include "ff.h"
|
|
|
|
|
#include "lcd_rgb.h"
|
2025-06-27 00:32:57 +08:00
|
|
|
|
#include "mymem.h"
|
2025-07-06 17:11:38 +08:00
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><D6BB>ѧϰʹ<CFB0>ã<EFBFBD>δ<EFBFBD><CEB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɣ<EFBFBD><C9A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>κ<EFBFBD><CEBA><EFBFBD>;
|
|
|
|
|
// ALIENTEK STM32F407<30><37><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
// MJPEG<45><47>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
|
|
|
|
// <20><><EFBFBD><EFBFBD>ԭ<EFBFBD><D4AD>@ALIENTEK
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̳:www.openedv.com
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:2014/7/20
|
|
|
|
|
// <20>汾<EFBFBD><E6B1BE>V1.0
|
|
|
|
|
// <20><>Ȩ<EFBFBD><C8A8><EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ؾ<EFBFBD><D8BE><EFBFBD>
|
|
|
|
|
// Copyright(C) <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӿƼ<D3BF><C6BC><EFBFBD><EFBFBD><EFBFBD>˾ 2009-2019
|
|
|
|
|
// All rights reserved
|
2025-06-27 00:32:57 +08:00
|
|
|
|
//*******************************************************************************
|
2025-07-06 17:11:38 +08:00
|
|
|
|
// <20><EFBFBD><DEB8><EFBFBD>Ϣ
|
|
|
|
|
// <20><>
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////
|
2025-06-27 00:32:57 +08:00
|
|
|
|
|
|
|
|
|
struct jpeg_decompress_struct *cinfo;
|
|
|
|
|
struct my_error_mgr *jerr;
|
2025-07-06 17:11:38 +08:00
|
|
|
|
u8 *jpegbuf; // jpeg<65><67><EFBFBD>ݻ<EFBFBD><DDBB><EFBFBD>ָ<EFBFBD><D6B8>
|
|
|
|
|
u32 jbufsize; // jpeg buf<75><66>С
|
|
|
|
|
u16 imgoffx, imgoffy; // ͼ<><CDBC><EFBFBD><EFBFBD>x,y<><79><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƫ<EFBFBD><C6AB><EFBFBD><EFBFBD>
|
2025-06-27 00:32:57 +08:00
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2025-07-06 17:11:38 +08:00
|
|
|
|
// <20><EFBFBD><F2B5A5BF>ٵ<EFBFBD><D9B5>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD><EFBFBD>,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٶ<EFBFBD>
|
|
|
|
|
#define MJPEG_MAX_MALLOC_SIZE 38 * 1024 // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Է<EFBFBD><D4B7><EFBFBD>38K<38>ֽ<EFBFBD>
|
|
|
|
|
|
|
|
|
|
u8 *jmembuf; // mjpeg<65><67><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ڴ<EFBFBD><DAB4><EFBFBD>
|
|
|
|
|
u32 jmempos; // <20>ڴ<EFBFBD><DAB4><EFBFBD>ָ<EFBFBD><D6B8>
|
|
|
|
|
|
|
|
|
|
// mjpeg<65><67><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>
|
|
|
|
|
void *mjpeg_malloc(u32 num) {
|
|
|
|
|
u32 curpos = jmempos; // <20>˴η<CBB4><CEB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>ַ
|
|
|
|
|
jmempos += num; // <20><>һ<EFBFBD>η<EFBFBD><CEB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>ַ
|
|
|
|
|
if (jmempos > MJPEG_MAX_MALLOC_SIZE) {
|
|
|
|
|
printf("mem error:%d,%d", curpos, num);
|
|
|
|
|
}
|
|
|
|
|
return (void *)&jmembuf[curpos]; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>뵽<EFBFBD><EBB5BD><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD>ַ
|
|
|
|
|
}
|
2025-06-27 00:32:57 +08:00
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2025-07-06 17:11:38 +08:00
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD>˳<EFBFBD>
|
|
|
|
|
static void my_error_exit(j_common_ptr cinfo) {
|
|
|
|
|
my_error_ptr myerr = (my_error_ptr)cinfo->err;
|
|
|
|
|
(*cinfo->err->output_message)(cinfo);
|
|
|
|
|
longjmp(myerr->setjmp_buffer, 1);
|
|
|
|
|
}
|
2025-06-27 00:32:57 +08:00
|
|
|
|
|
2025-07-06 17:11:38 +08:00
|
|
|
|
METHODDEF(void)
|
|
|
|
|
my_emit_message(j_common_ptr cinfo, int msg_level) {
|
|
|
|
|
my_error_ptr myerr = (my_error_ptr)cinfo->err;
|
|
|
|
|
if (msg_level < 0) {
|
|
|
|
|
printf("emit msg:%d\r\n", msg_level);
|
|
|
|
|
longjmp(myerr->setjmp_buffer, 1);
|
|
|
|
|
}
|
2025-06-27 00:32:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
2025-07-06 17:11:38 +08:00
|
|
|
|
// <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>Դ,<2C><>ִ<EFBFBD><D6B4><EFBFBD>κβ<CEBA><CEB2><EFBFBD>
|
|
|
|
|
static void init_source(j_decompress_ptr cinfo) {
|
|
|
|
|
// <20><><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>κ<EFBFBD><CEBA><EFBFBD><EFBFBD><EFBFBD>.
|
|
|
|
|
return;
|
2025-06-27 00:32:57 +08:00
|
|
|
|
}
|
2025-07-06 17:11:38 +08:00
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>뻺<EFBFBD><EBBBBA><EFBFBD><EFBFBD>,һ<><D2BB><EFBFBD>Զ<EFBFBD>ȡ<EFBFBD><C8A1>֡<EFBFBD><D6A1><EFBFBD><EFBFBD>
|
|
|
|
|
static boolean fill_input_buffer(j_decompress_ptr cinfo) {
|
|
|
|
|
if (jbufsize == 0) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
{
|
|
|
|
|
// printf("jd read off\r\n");
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
jpegbuf[0] = (u8)0xFF;
|
|
|
|
|
jpegbuf[1] = (u8)JPEG_EOI;
|
|
|
|
|
cinfo->src->next_input_byte = jpegbuf;
|
|
|
|
|
cinfo->src->bytes_in_buffer = 2;
|
|
|
|
|
} else {
|
|
|
|
|
cinfo->src->next_input_byte = jpegbuf;
|
|
|
|
|
cinfo->src->bytes_in_buffer = jbufsize;
|
|
|
|
|
jbufsize -= jbufsize;
|
|
|
|
|
}
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
// <20><><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>,<2C><><EFBFBD><EFBFBD>num_bytes<65><73><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
static void skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
|
|
|
|
|
/* Just a dumb implementation for now. Could use fseek() except
|
|
|
|
|
* it doesn't work on pipes. Not clear that being smart is worth
|
|
|
|
|
* any trouble anyway --- large skips are infrequent.
|
|
|
|
|
*/
|
|
|
|
|
if (num_bytes > 0) {
|
|
|
|
|
while (num_bytes > (long)cinfo->src->bytes_in_buffer) {
|
|
|
|
|
num_bytes -= (long)cinfo->src->bytes_in_buffer;
|
|
|
|
|
(void)cinfo->src->fill_input_buffer(cinfo);
|
|
|
|
|
/* note we assume that fill_input_buffer will never
|
|
|
|
|
* return FALSE, so suspension need not be handled.
|
|
|
|
|
*/
|
2025-06-27 00:32:57 +08:00
|
|
|
|
}
|
2025-07-06 17:11:38 +08:00
|
|
|
|
cinfo->src->next_input_byte += (size_t)num_bytes;
|
|
|
|
|
cinfo->src->bytes_in_buffer -= (size_t)num_bytes;
|
|
|
|
|
}
|
2025-06-27 00:32:57 +08:00
|
|
|
|
}
|
2025-07-06 17:11:38 +08:00
|
|
|
|
// <20>ڽ<EFBFBD><DABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<2C><>jpeg_finish_decompress<73><73><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
static void term_source(j_decompress_ptr cinfo) {
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD>κδ<CEBA><CEB4><EFBFBD>
|
|
|
|
|
return;
|
2025-06-27 00:32:57 +08:00
|
|
|
|
}
|
2025-07-06 17:11:38 +08:00
|
|
|
|
// <20><>ʼ<EFBFBD><CABC>jpeg<65><67><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ
|
|
|
|
|
static void jpeg_filerw_src_init(j_decompress_ptr cinfo) {
|
|
|
|
|
if (cinfo->src == NULL) /* first time for this JPEG object? */
|
|
|
|
|
{
|
|
|
|
|
cinfo->src = (struct jpeg_source_mgr *)(*cinfo->mem->alloc_small)(
|
|
|
|
|
(j_common_ptr)cinfo, JPOOL_PERMANENT, sizeof(struct jpeg_source_mgr));
|
|
|
|
|
}
|
|
|
|
|
cinfo->src->init_source = init_source;
|
|
|
|
|
cinfo->src->fill_input_buffer = fill_input_buffer;
|
|
|
|
|
cinfo->src->skip_input_data = skip_input_data;
|
|
|
|
|
cinfo->src->resync_to_restart =
|
|
|
|
|
jpeg_resync_to_restart; /* use default method */
|
|
|
|
|
cinfo->src->term_source = term_source;
|
|
|
|
|
cinfo->src->bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
|
|
|
|
|
cinfo->src->next_input_byte = NULL; /* until buffer loaded */
|
2025-06-27 00:32:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
2025-07-06 17:11:38 +08:00
|
|
|
|
// mjpeg <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>
|
|
|
|
|
// offx,offy:x,y<><79><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƫ<EFBFBD><C6AB>
|
|
|
|
|
// <20><><EFBFBD><EFBFBD>ֵ:0,<2C>ɹ<EFBFBD>;
|
|
|
|
|
// 1,ʧ<><CAA7>
|
|
|
|
|
u8 mjpegdec_init(u16 offx, u16 offy) {
|
|
|
|
|
cinfo = mymalloc(sizeof(struct jpeg_decompress_struct));
|
|
|
|
|
jerr = mymalloc(sizeof(struct my_error_mgr));
|
|
|
|
|
// <20><><EFBFBD><EFBFBD>sram<61><6D><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߽<EFBFBD><DFBD><EFBFBD><EFBFBD>ٶ<EFBFBD>--2020.6.2
|
|
|
|
|
jmembuf = mymalloc_fast(MJPEG_MAX_MALLOC_SIZE); // MJPEG<45><47><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
if (cinfo == 0 || jerr == 0 || jmembuf == 0) {
|
|
|
|
|
mjpegdec_free();
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
// <20><><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD>x,y<><79><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƫ<EFBFBD><C6AB><EFBFBD><EFBFBD>
|
|
|
|
|
imgoffx = offx;
|
|
|
|
|
imgoffy = offy;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
// mjpeg<65><67><EFBFBD><EFBFBD>,<2C>ͷ<EFBFBD><CDB7>ڴ<EFBFBD>
|
|
|
|
|
void mjpegdec_free(void) {
|
|
|
|
|
myfree(cinfo);
|
|
|
|
|
myfree(jerr);
|
|
|
|
|
myfree(jmembuf);
|
2025-06-27 00:32:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
2025-07-06 17:11:38 +08:00
|
|
|
|
// <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>JPEGͼƬ
|
|
|
|
|
// buf:jpeg<65><67><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
// bsize:<3A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С
|
|
|
|
|
// <20><><EFBFBD><EFBFBD>ֵ:0,<2C>ɹ<EFBFBD>
|
|
|
|
|
// <20><><EFBFBD><EFBFBD>,<2C><><EFBFBD><EFBFBD>
|
|
|
|
|
u8 mjpegdec_decode(u8 *buf, u32 bsize) {
|
|
|
|
|
JSAMPARRAY buffer;
|
|
|
|
|
if (bsize == 0)
|
|
|
|
|
return 1;
|
|
|
|
|
jpegbuf = buf;
|
|
|
|
|
jbufsize = bsize;
|
|
|
|
|
jmempos = 0; // MJEPG<50><47><EFBFBD><EFBFBD>,<2C><><EFBFBD>´<EFBFBD>0<EFBFBD><30>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>
|
|
|
|
|
|
|
|
|
|
cinfo->err = jpeg_std_error(&jerr->pub);
|
|
|
|
|
jerr->pub.error_exit = my_error_exit;
|
|
|
|
|
jerr->pub.emit_message = my_emit_message;
|
|
|
|
|
// if(bsize>20*1024)printf("s:%d\r\n",bsize);
|
|
|
|
|
if (setjmp(jerr->setjmp_buffer)) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
{
|
|
|
|
|
jpeg_abort_decompress(cinfo);
|
|
|
|
|
jpeg_destroy_decompress(cinfo);
|
|
|
|
|
return 2;
|
|
|
|
|
}
|
|
|
|
|
jpeg_create_decompress(cinfo);
|
|
|
|
|
jpeg_filerw_src_init(cinfo);
|
|
|
|
|
jpeg_read_header(cinfo, TRUE);
|
|
|
|
|
cinfo->dct_method = JDCT_IFAST;
|
|
|
|
|
cinfo->do_fancy_upsampling = 0;
|
|
|
|
|
jpeg_start_decompress(cinfo);
|
|
|
|
|
extern void jdmerge_setlcdaddr(unsigned short *addr);
|
|
|
|
|
unsigned short *lcd_addr = (unsigned short *)LCD_GetDrawAddr();
|
|
|
|
|
// lcd_addr+=LCD_GetLcdSizeX()*LCD_GetLcdSizeY()-1-(imgoffx+imgoffy*LCD_GetLcdSizeX());
|
|
|
|
|
jdmerge_setlcdaddr(lcd_addr); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾλ<CABE><CEBB>
|
|
|
|
|
while (cinfo->output_scanline < cinfo->output_height) {
|
|
|
|
|
jpeg_read_scanlines(cinfo, buffer, 1);
|
|
|
|
|
}
|
|
|
|
|
jpeg_finish_decompress(cinfo);
|
|
|
|
|
jpeg_destroy_decompress(cinfo);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|