cancel
Showing results for 
Search instead for 
Did you mean: 

MJPEG Video Decoding (stm32h747I)

AFato.3
Associate II

Hi,

I recently bought an STM32H747I-DISCO board and I'm trying to run the JPEG_MJPEG_VideoDecoding code example with an external display. The code works fine with the on-board display, but I'm struggling to get it working with an external display that uses a GC9A01 driver.

I'm confident the issue isn't with the new display or its associated code because I've successfully tested it with static JPEG decoding (not MJPEG). I suspect the problem lies within the code example I'm trying to modify, specifically in the DMA2D section. It appears that the external DRAM is not written to during the final phase of the decoding by the DMA2D peripheral. As a result, when I run my lcd_draw() function, it shows garbage on the display.

My modifications to the original code involved disabling all on-board LCD functions and replacing them with my own LCD functions.

Can you help me understand why it doesn't work?

It follows the part of code I modified and an image. 

Here is the main code I modified; 

int main(void)
{

  uint32_t isfirstFrame =0;
  //uint32_t startTime = 0;
  uint32_t file_error = 0, sd_detection_error = 0;  
  uint32_t jpegOutDataAdreess = JPEG_OUTPUT_DATA_BUFFER0;
  uint32_t FrameType = 0;


  /* Configure the MPU attributes as Write Through for SDRAM*/
  MPU_Config();
   
  /* Enable the CPU Cache */
  CPU_CACHE_Enable();
  
  HAL_Init();
  
  /* Configure the system clock to 400 MHz */
  SystemClock_Config();
  
  MX_GPIO_Init();
  MX_SPI5_Init();

  GC9A01_init();
 
 /*Initialize The SDRAM */  
  BSP_SDRAM_Init(0);

  /* Initialize the LCD */
  //BSP_LCD_Init(0, LCD_ORIENTATION_LANDSCAPE);
  //UTIL_LCD_SetFuncDriver(&LCD_Driver);
  //UTIL_LCD_SetLayer(0);
  //UTIL_LCD_Clear(UTIL_LCD_COLOR_WHITE);
  //UTIL_LCD_SetFont(&Font24);
  
  //BSP_LCD_GetXSize(0 ,&LCD_X_Size);
  //BSP_LCD_GetYSize(0 ,&LCD_Y_Size);
  
  /*##-2- Initialize the HW JPEG Codec  ######################################*/
  /* Init the HAL JPEG driver */
  JPEG_Handle.Instance = JPEG;
  HAL_JPEG_Init(&JPEG_Handle);    

  /*##-3- Link the micro SD disk I/O driver ##################################*/
  if(FATFS_LinkDriver(&SD_Driver, SDPath) == 0)
  {
    /*##-4- Init the SD Card #################################################*/
    SD_Initialize();

    if(BSP_SD_IsDetected(0))
    {    
      /*##-5- Register the file system object to the FatFs module ##############*/
      if(f_mount(&SDFatFs, (TCHAR const*)SDPath, 0) == FR_OK)
      {
        /*##-6- Open the MJPEG avi file with read access #######################*/
        if(f_open(&MJPEG_File, "video.avi", FA_READ) == FR_OK)
        {

          isfirstFrame = 1;
          FrameRate = 0;

          /* parse the AVI file Header*/
          if(AVI_ParserInit(&AVI_Handel, &MJPEG_File, MJPEG_VideoBuffer, MJPEG_VID_BUFFER_SIZE, MJPEG_AudioBuffer, MJPEG_AUD_BUFFER_SIZE) != 0)
          {

            while(1);

          }
          
          do
          {         
            
            FrameType = AVI_GetFrame(&AVI_Handel, &MJPEG_File);
            
            if(FrameType == AVI_VIDEO_FRAME)
            {

              AVI_Handel.CurrentImage ++;
              
              /*##-7- Start decoding the current JPEG frame with DMA (Not Blocking ) Method ################*/
              JPEG_Decode_DMA(&JPEG_Handle,(uint32_t) MJPEG_VideoBuffer ,AVI_Handel.FrameSize, jpegOutDataAdreess );
              
              /*##-8- Wait till end of JPEG decoding ###########################*/
              while(Jpeg_HWDecodingEnd == 0);
              
              if(isfirstFrame == 1)
              {

                isfirstFrame = 0;              

                /*##-9- Get JPEG Info  #########################################*/
                HAL_JPEG_GetInfo(&JPEG_Handle, &JPEG_Info); 
                
                /*##-10- Initialize the DMA2D ##################################*/
                DMA2D_Init(JPEG_Info.ImageWidth, JPEG_Info.ImageHeight, JPEG_Info.ChromaSubsampling);

              }

              /*##-11- Copy the Decoded frame to the display frame buffer using the DMA2D #*/            
              DMA2D_CopyBuffer((uint32_t *)jpegOutDataAdreess, (uint32_t *)LCD_FRAME_BUFFER, JPEG_Info.ImageWidth, JPEG_Info.ImageHeight);
              
              jpegOutDataAdreess = (jpegOutDataAdreess == JPEG_OUTPUT_DATA_BUFFER0) ? JPEG_OUTPUT_DATA_BUFFER1 : JPEG_OUTPUT_DATA_BUFFER0;
              
            }
            
		    uint16_t width = JPEG_Info.ImageWidth;
			uint16_t height = JPEG_Info.ImageHeight;

		    uint16_t xPos = (LCD_X_Size - width)/2;					// Center the image in x
		    uint16_t yPos = (LCD_Y_Size - height)/2;					// Center the image in y

		    doubleFormat pOut;
		    pOut.u8Arr = (uint8_t *)LCD_FRAME_BUFFER;

		    depth24To16(&pOut, width*height, 3);

		    // Display the image
		    lcd_draw(xPos, yPos, width, height, pOut.u8Arr);

          }while(AVI_Handel.CurrentImage  <  AVI_Handel.aviInfo.TotalFrame);
          
          HAL_DMA2D_PollForTransfer(&DMA2D_Handle, 50);  /* wait for the Last DMA2D transfer to ends */

          /*Close the avi file*/
          f_close(&MJPEG_File);

        }
        else /* Can't Open avi file*/
        {

          file_error = 1;          

        }    

      }

    }
    else
    {

      sd_detection_error = 1;

    }

    if((file_error != 0) || (sd_detection_error != 0))
    {

      while(1);

    }    

  }
 
  /* Infinite loop */
  while (1);

}

 

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
AFato.3
Associate II

Hi @STOne-32 ,

 

Thank you for your reply. I found out the problem, it was that the low level configuration of the DMA2D in that example was not placed in the stm32h7xx_hal_msp.c file as for the other peripherals, but it was in another file which I excluded because not relevant for my application. I solved the problem copying that part of the code into the stm32h7xx_hal_msp.c file. 

View solution in original post

2 REPLIES 2
STOne-32
ST Employee

Dear @AFato.3 ,

 

May be it is a Cache coherency issue , CPU / Cortex-M7 is trying to display data generated from DMA2D .  Is that possible to add

 CleanIvalidate before lcd_draw() function and let us know if it helps ?

Ciao

STOne-32

AFato.3
Associate II

Hi @STOne-32 ,

 

Thank you for your reply. I found out the problem, it was that the low level configuration of the DMA2D in that example was not placed in the stm32h7xx_hal_msp.c file as for the other peripherals, but it was in another file which I excluded because not relevant for my application. I solved the problem copying that part of the code into the stm32h7xx_hal_msp.c file.