cancel
Showing results for 
Search instead for 
Did you mean: 

How do decompress JPEG from DCMI using LibJPEG and FreeRTOS?

Florian Moser
Senior

I'm using an STM32H7A3IITxQ and trying to get an image (JPEG, 320x240) from a camera via DCMI, decompress it and display it on a screen via LTDC.

It currently seems like I'm getting a valid JPEG picture from the camera, as there is "Start of Image" and "End of Image" in the buffer and about 4kBytes of data. (https://de.wikipedia.org/wiki/JPEG_File_Interchange_Format)

I'm also able to display data on the screen via LTDC. (Set up TouchGFX and FreeRTOS)

My current problem is the decompression of the JPEG with LibJPEG. I copied the code from an example and modified it, since my JPEG is in a buffer and not a file on a SD-card.

(STM32Cube_FW_F4_V1.27.0\Projects\STM32446E_EVAL\Applications\LibJPEG\LibJPEG_Decoding)

void jpeg_startDecode(uint8_t* inBuf, uint32_t inBufNum, uint8_t* outBuf, uint32_t outBufSize)
{
	  /* Decode JPEG Image */
	  JSAMPROW buffer[2] = {0}; /* Output row buffer */
 
	  buffer[0] = outBuf;
 
	  /* Step 1: allocate and initialize JPEG decompression object */
	  cinfo.err = jpeg_std_error(&jerr);
 
	  /* Initialize the JPEG decompression object */
	  jpeg_create_decompress(&cinfo);
 
	  jpeg_mem_src (&cinfo, inBuf, inBufNum);
 
	  //jpeg_stdio_src (&cinfo, file);
 
	  /* Step 3: read image parameters with jpeg_read_header() */
	  jpeg_read_header(&cinfo, TRUE);
 
	  /* Step 4: set parameters for decompression */
	  cinfo.dct_method = JDCT_FLOAT;
 
	  /* Step 5: start decompressor */
	  jpeg_start_decompress(&cinfo);
 
	  if(cinfo.output_height * cinfo.output_width * 3 > outBufSize)
	  {
		  return;
	  }
 
	  (void) jpeg_read_scanlines(&cinfo, buffer, cinfo.output_height);
 
 
	  /* Step 6: Finish decompression */
	  jpeg_finish_decompress(&cinfo);
 
	  /* Step 7: Release JPEG decompression object */
	  jpeg_destroy_decompress(&cinfo);
}

After jpeg_start_decompress has finished cinfo.output_height is 240 and cinfo.output_width is 320, as I expect them to be. The if-statement after that is always false, as the buffer is large enough for the image.

The problem is that the processor gets into an infinite loop a short while after executing jpeg_start_decompress (jpeg_startDecode does not return in any case, but the time is kinda "random"). The infinite loop comes from this assert:

//port.c 
configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
//ucCurrentPriority is 144 here and ucMaxSysCallPriority is 244.
 
//FreeRTOSConfig.h
#define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );}

The interrupt triggering this was the LTDC global interrupt. LTDC LineEvent to be exact.

As there is a description in the source (port.c) on why the assert can fail, I checked my NVIC.

/* The following assertion will fail if a service routine (ISR) for
an interrupt that has been assigned a priority above
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
function.  ISR safe FreeRTOS API functions must *only* be called
from interrupts that have been assigned a priority at or below
configMAX_SYSCALL_INTERRUPT_PRIORITY.
 
Numerically low interrupt priority numbers represent logically high
interrupt priorities, therefore the priority of the interrupt must
be set to a value equal to or numerically *higher* than
configMAX_SYSCALL_INTERRUPT_PRIORITY.
 
Interrupts that	use the FreeRTOS API must not be left at their
default priority of	zero as that is the highest possible priority,
which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
and	therefore also guaranteed to be invalid.
 
FreeRTOS maintains separate thread and ISR API functions to ensure
interrupt entry is as fast and simple as possible.
 
The following links provide detailed information:
http://www.freertos.org/RTOS-Cortex-M3-M4.html
http://www.freertos.org/FAQHelp.html */

0693W00000LwNHZQA3.jpg0693W00000LwNSDQA3.png 

I really don't see any problem with the interrupt priorities here.

Does someone has an idea what went wrong here?

Thanks in advance!

1 REPLY 1
Florian Moser
Senior

For everyone who has the same problem:

I switched to the hardware JPEG Codec, since my processor has one and it is working fine with the same setup.

I haven't solved the problem with LibJPEG and I will not.