cancel
Showing results for 
Search instead for 
Did you mean: 

DMA2D, facing issues in YCBCR to RGB conversion based on chroma-subsampling type on U5G7

Hareesh_S
Associate III

Background - TouchGFX based HMI application where I want to display JPEGs I am streaming.
I have setup the bitmap cache for TouchGFX and can confirm it works as expected with raw RGB565/888 bitmaps.
I am trying to integrate the JPEG codec to stream JPEG data instead of the raw bitmaps, to reduce latency.

DMA2D is *not* configured to be used by TouchGFX, so that I can use it to convert the output of the JPEG codec to RGB565 format to store in my bitmap cache, that touchGFX draws. Additionally, I have configured my IOC not to generate the DMA2D init function call.

For JPEG codec and DMA2D code, I have referred to the H7 example project (JPEG_DecodeFromFlashDMA) provided by ST.

When I test with few sample JPEGs, it works as expected and displays accurately, but does not for other samples.
It seems to work with CSS 4:2:0 images only, and not with CSS 4:4:4 or 4:2:2 images - It seems to be the JPEG decode works as expected, and the DMA2D transformation(?) is what is causing issues.

I have attached the relevant snippets of my code below.

 

HAL_JPEG_Decode(&hjpeg, bitmap_rx, jpeg_size, JPEG_decoded,
		BITMAP_BUFFER_SIZE, 100);

HAL_JPEG_GetInfo(&hjpeg, &JPEG_Info);

DMA2D_YCBCR_To_RGB(JPEG_decoded, bitmap->bitmap_pointer,
				JPEG_Info.ChromaSubsampling, JPEG_Info.ImageWidth,
				JPEG_Info.ImageHeight);

 

bitmap->bitmap_pointer is the pointer assigned by touchGFX when creating the bitmap cache
bitmap_rx contains the bytestream of a JPEG encoded image, and JPEG_decoded contains the output of the decoded JPEG. 

 

void DMA2D_YCBCR_To_RGB(uint8_t *source_pointer, uint8_t *destination_pointer,
		uint32_t chroma_subsampling, uint16_t x_size, uint16_t y_size) {

	uint32_t css_mode = DMA2D_CSS_422;
	uint32_t input_line_offset = 0;

	switch (chroma_subsampling) {
	case JPEG_420_SUBSAMPLING:
		css_mode = DMA2D_CSS_420;

		input_line_offset = x_size % 16;
		if (input_line_offset != 0) {
			input_line_offset = 16 - input_line_offset;
		}
		break;

	case JPEG_422_SUBSAMPLING:
		css_mode = DMA2D_CSS_422;

		inputLineOffset = xsize % 16;
		if (inputLineOffset != 0) {
			inputLineOffset = 16 - inputLineOffset;
		}
		break;

	case JPEG_444_SUBSAMPLING:
		css_mode = DMA2D_NO_CSS;

		input_line_offset = x_size % 8;
		if (input_line_offset != 0) {
			input_line_offset = 8 - input_line_offset;
		}
		break;

	default:
		break;
	}

	hdma2d.Instance = DMA2D;
	hdma2d.Init.Mode = DMA2D_M2M_PFC;
	hdma2d.Init.ColorMode = DMA2D_OUTPUT_RGB565;
	hdma2d.Init.OutputOffset = 0;
	hdma2d.Init.BytesSwap = DMA2D_BYTES_REGULAR;
	hdma2d.Init.LineOffsetMode = DMA2D_LOM_PIXELS;

	hdma2d.LayerCfg[1].InputOffset = input_line_offset;
	hdma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_YCBCR;
	hdma2d.LayerCfg[1].ChromaSubSampling = css_mode;

	hdma2d.LayerCfg[1].AlphaMode = DMA2D_REPLACE_ALPHA;
	hdma2d.LayerCfg[1].InputAlpha = 0xFF;

	hdma2d.LayerCfg[1].AlphaInverted = DMA2D_REGULAR_ALPHA;
	hdma2d.LayerCfg[1].RedBlueSwap = DMA2D_RB_REGULAR;

	if (HAL_DMA2D_Init(&hdma2d) != HAL_OK) {
		Error_Handler();
	}
	if (HAL_DMA2D_ConfigLayer(&hdma2d, 1) != HAL_OK) {
		Error_Handler();
	}

	HAL_DMA2D_Start(&hdma2d, (uint32_t) source_pointer,
			(uint32_t) destination_pointer, x_size, y_size);

	HAL_DMA2D_PollForTransfer(&hdma2d, 1000);
}

 

 I have also attached sample images for reference of the accurately displayed JPEG (CSS 4:2:0) and incorrectly displayed JPEG, along with pictures of how it is rendered on the display.

Any guidance/assistance would be much appreciated!

0 REPLIES 0