guest@amper.me /blog $

Использование аппаратного сжатия в jpeg

Есть у меня в наличии девборда на Samsung'овском процессоре S5PV210.
В качестве эксперимента изучаю возможности современных ARM процессоров.
Данный образец обладает мультиформатным видео кодеком, jpeg кодеком, а так же включает SIMD расширение Neon. Грубо говоря - векторная считалка. Конкретно остановимся на jpeg кодеке.

Использование кодека, в целом, достаточно простое. Есть инициализация, настройка, сам процесс сжатия и получение результата.
Все основные файлы лежат в SDK, опишу только функции работы с данными.
Энкодер объявлен в виде класса, поэтому создаем экземпляр объекта:
Код c:
JpegEncoder jpgEnc;

Инициализируем энкодер:
Код c:
jpgEnc.create();

сама функция сжатия в jpeg:
Код c:
bool yuv2jpg(unsigned char * yuv, unsigned int yuv_sz, unsigned char * jpeg, unsigned int * jpeg_sz)
{
	int inFormat = JPG_MODESEL_YCBCR;	//входящий формат - YUV
	int outFormat = JPG_422;		//формат JPEG - 4:2:2
	int jpegQuality = JPG_QUALITY_LEVEL_2;	//Качество jpeg - 80
	//устанавливаем форматы
	if (jpgEnc.setConfig(JPEG_SET_ENCODE_IN_FORMAT, inFormat) != JPG_SUCCESS)
		printf("[JPEG_SET_ENCODE_IN_FORMAT] Error\n");

	if (jpgEnc.setConfig(JPEG_SET_SAMPING_MODE, outFormat) != JPG_SUCCESS)
		printf("[JPEG_SET_SAMPING_MODE] Error\n");

	//устанавливаем качество
	if (jpgEnc.setConfig(JPEG_SET_ENCODE_QUALITY, jpegQuality) != JPG_SUCCESS)
		printf("[JPEG_SET_ENCODE_QUALITY] Error\n");

	//устанавливаем ширину
	if (jpgEnc.setConfig(JPEG_SET_ENCODE_WIDTH, 640) != JPG_SUCCESS)
		printf("[JPEG_SET_ENCODE_WIDTH] Error\n");

	//и высоту изображения
	if (jpgEnc.setConfig(JPEG_SET_ENCODE_HEIGHT, 480) != JPG_SUCCESS)
		printf("[JPEG_SET_ENCODE_HEIGHT] Error\n");

	//получаем адрес входящего буфера
	unsigned char *pInBuf = (unsigned char *)jpgEnc.getInBuf(yuv_sz);

	if (pInBuf == NULL) {
		printf("JPEG input buffer is NULL!!\n");
		return -1;
	}

	//копируем исходное изображение в буфер кодека
	memcpy(pInBuf, yuv, yuv_sz);

	//собственно, сам процесс сжатия
	jpgEnc.encode(outlen, NULL);

	uint64_t outbuf_size;
	//достаем адрес результата
	unsigned char *pOutBuf = (unsigned char *)jpgEnc.getOutBuf(&outbuf_size);

	if (pOutBuf == NULL) {
		printf("JPEG output buffer is NULL!\n");
		return false;
	}

	//и копируем его в выходной буфер
	memcpy(jpeg, pOutBuf, outbuf_size);

	return true;
}

В процессе была найдена забавная особенность: всю нагрузку на ЦП во время процесса составляет копирование исходного изображения в буфер. При использовании вебкамеры в разрешении 640х480 с 24fps загрузка ЦП составляет порядка 20%. При использовании собственной реализации функции mempcy для использования Neon загрузку удалось снизить до 8%, что, правда, все равно меня не устраивает.


© Amper, 2011-2018
Время генерации страницы: 0.03с. SQL запросов: 2