224 lines
6.2 KiB
C
224 lines
6.2 KiB
C
#include "mjpeg.h"
|
||
#include "mymem.h"
|
||
#include "ff.h"
|
||
#include "lcd_rgb.h"
|
||
//////////////////////////////////////////////////////////////////////////////////
|
||
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
|
||
//ALIENTEK STM32F407开发板
|
||
//MJPEG视频处理 代码
|
||
//正点原子@ALIENTEK
|
||
//技术论坛:www.openedv.com
|
||
//创建日期:2014/7/20
|
||
//版本:V1.0
|
||
//版权所有,盗版必究。
|
||
//Copyright(C) 广州市星翼电子科技有限公司 2009-2019
|
||
//All rights reserved
|
||
//*******************************************************************************
|
||
//修改信息
|
||
//无
|
||
//////////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
struct jpeg_decompress_struct *cinfo;
|
||
struct my_error_mgr *jerr;
|
||
u8 *jpegbuf; //jpeg数据缓存指针
|
||
u32 jbufsize; //jpeg buf大小
|
||
u16 imgoffx,imgoffy; //图像在x,y方向的偏移量
|
||
|
||
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
//简单快速的内存分配,以提高速度
|
||
#define MJPEG_MAX_MALLOC_SIZE 38*1024 //最大可以分配38K字节
|
||
|
||
|
||
u8 *jmembuf; //mjpeg解码的 内存池
|
||
u32 jmempos; //内存池指针
|
||
|
||
//mjpeg申请内存
|
||
void* mjpeg_malloc(u32 num)
|
||
{
|
||
u32 curpos=jmempos; //此次分配的起始地址
|
||
jmempos+=num; //下一次分配的起始地址
|
||
if(jmempos>MJPEG_MAX_MALLOC_SIZE)
|
||
{
|
||
printf("mem error:%d,%d",curpos,num);
|
||
}
|
||
return (void *)&jmembuf[curpos]; //返回申请到的内存首地址
|
||
}
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
//错误退出
|
||
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);
|
||
}
|
||
|
||
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);
|
||
}
|
||
}
|
||
|
||
//初始化资源,不执行任何操作
|
||
static void init_source(j_decompress_ptr cinfo)
|
||
{
|
||
//不需要做任何事情.
|
||
return;
|
||
}
|
||
//填充输入缓冲区,一次性读取整帧数据
|
||
static boolean fill_input_buffer(j_decompress_ptr cinfo)
|
||
{
|
||
if(jbufsize==0)//结束了
|
||
{
|
||
//printf("jd read off\r\n");
|
||
//填充结束符
|
||
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;
|
||
}
|
||
//在文件里面,跳过num_bytes个数据
|
||
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.
|
||
*/
|
||
}
|
||
cinfo->src->next_input_byte += (size_t) num_bytes;
|
||
cinfo->src->bytes_in_buffer -= (size_t) num_bytes;
|
||
}
|
||
}
|
||
//在解码结束后,被jpeg_finish_decompress函数调用
|
||
static void term_source(j_decompress_ptr cinfo)
|
||
{
|
||
//不做任何处理
|
||
return;
|
||
}
|
||
//初始化jpeg解码数据源
|
||
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 */
|
||
}
|
||
|
||
|
||
//mjpeg 解码初始化
|
||
//offx,offy:x,y方向的偏移
|
||
//返回值:0,成功;
|
||
// 1,失败
|
||
u8 mjpegdec_init(u16 offx,u16 offy)
|
||
{
|
||
cinfo=mymalloc(sizeof(struct jpeg_decompress_struct));
|
||
jerr=mymalloc(sizeof(struct my_error_mgr));
|
||
//分配sram区的内存以提高解码速度--2020.6.2
|
||
jmembuf=mymalloc_fast(MJPEG_MAX_MALLOC_SIZE);//MJPEG解码内存池申请
|
||
if(cinfo==0||jerr==0||jmembuf==0)
|
||
{
|
||
mjpegdec_free();
|
||
return 1;
|
||
}
|
||
//保存图像在x,y方向的偏移量
|
||
imgoffx=offx;
|
||
imgoffy=offy;
|
||
return 0;
|
||
}
|
||
//mjpeg结束,释放内存
|
||
void mjpegdec_free(void)
|
||
{
|
||
myfree(cinfo);
|
||
myfree(jerr);
|
||
myfree(jmembuf);
|
||
}
|
||
|
||
//解码一副JPEG图片
|
||
//buf:jpeg数据流数组
|
||
//bsize:数组大小
|
||
//返回值:0,成功
|
||
// 其他,错误
|
||
u8 mjpegdec_decode(u8* buf,u32 bsize)
|
||
{
|
||
JSAMPARRAY buffer;
|
||
if(bsize==0)return 1;
|
||
jpegbuf=buf;
|
||
jbufsize=bsize;
|
||
jmempos=0;//MJEPG解码,重新从0开始分配内存
|
||
|
||
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)) //错误处理
|
||
{
|
||
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);//设置显示位置
|
||
while (cinfo->output_scanline < cinfo->output_height)
|
||
{
|
||
jpeg_read_scanlines(cinfo, buffer, 1);
|
||
}
|
||
jpeg_finish_decompress(cinfo);
|
||
jpeg_destroy_decompress(cinfo);
|
||
return 0;
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|