将视频文件解码成图片的过程中,我使用了libjpeg-turbo将RGB数据转成JPEG,后来在程序运行中发现有大量的内存溢出。
以下是RGB转JPEG的函数:
int RGB_2_JPG(unsigned char *pRGBBuffer, int width, int height, unsigned char **outbuf, unsigned long *outsize)
{
struct jpeg_compress_struct jcs;
struct jpeg_error_mgr jem;
jcs.err = jpeg_std_error(&jem);
jpeg_create_compress(&jcs);
jpeg_mem_dest(&jcs, &(*outbuf), outsize);
jcs.image_width = width;
jcs.image_height = height;
jcs.input_components = 3;
jcs.in_color_space = JCS_RGB;
jpeg_set_defaults(&jcs);
jpeg_set_quality(&jcs, 80, TRUE);
jpeg_start_compress(&jcs, TRUE);
JSAMPROW row_pointer[1];
int row_stride;
row_stride = width * 3;
while (jcs.next_scanline < jcs.image_height)
{
row_pointer[0] = &pRGBBuffer[jcs.next_scanline * row_stride];
(void)jpeg_write_scanlines(&jcs, row_pointer, 1);
}
jpeg_finish_compress(&jcs);
jpeg_destroy_compress(&jcs);
return 0;
}
形参中的 outbuf,是jpeg文件转换后的内存地址,已经预先开辟好内存空间。按理说,这个outbuf的地址是不会被改变的,但是在某些情况下它在执行过上面的函数后会指向新的内存地址。因此造成了之前已开辟好的内存空间无法回收,内存开销越来越大,最终程序被操作系统kill。
我的解决办法是:在调用转换函数前用另一个指针保存这个地址,当返回后两个地址不一致,则将两个指针都free()。
unsigned char *p = (unsigned char*)malloc(pCodecCtx->width * pCodecCtx->height);
unsigned char *pcheck; //p的保险指针
...
pcheck = p;
//printf("=== addr === %p", p);
RGB_2_JPG(pFrameFMT->data[0], pCodecCtx->width, pCodecCtx->height, (unsigned char**)&p, &sz);
//printf("=== addr === %p\n", p);
std::ofstream fout(output, std::ios_base::binary);
fout.write((char*)p, sz);
fout.close();
if (p != pcheck)
{
free(p);
p = pcheck;
//printf("=== addr is changed, free twice ===\n");
}