Files
player/Project/Src/MJPEG/mjpeg.c

187 lines
5.7 KiB
C
Raw Normal View History

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;
}