Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Скорость декодирования JPEG
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Александр П.
Добрый день.
Возникла проблема со скоростью декодирования JPEG. Размеры изображений 1280x800 (100kb).
Прикрутил к проекту библиотеку libjpeg. Работает, но очень медленно (~ 1 кадр в сек)
Делаю все следующим образом...
libjpeg.h
CODE
typedef enum _EJpegInput
{
/** error/unspecified */
JPG_DATA_UNKNOWN,

/** monochrome */
JPG_DATA_GRAYSCALE,

/** red/green/blue */
JPG_DATA_RGB,

/** Y/Cb/Cr (also known as YUV) */
JPG_DATA_YCbCr,

/** C/M/Y/K */
JPG_DATA_CMYK,

/** Y/Cb/Cr/K */
JPG_DATA_YCCK
} EJpegInput;

typedef enum _EJpegMethod
{
/** slow but accurate integer algorithm */
JPG_METHOD_ISLOW,

/** faster, less accurate integer method */
JPG_METHOD_IFAST,

/** floating-point: accurate, fast on fast HW */
JPG_METHOD_FLOAT
} EJpegMethod;

typedef struct _SJPEGData
{
// Source
uint8_t* pucSrc;
uint32_t dwSrcLength;

// Destination
uint8_t* pucDst;
uint32_t dwDstLength;

// Dimensions
uint32_t dwHeight;
uint32_t dwWidth;
uint32_t dwBPP;

// JPEG algo parameters
uint32_t dwQuality;
EJpegInput eInput;
EJpegMethod eMethod;

uint32_t (*cbk)( uint8_t*, uint32_t, uint32_t, uint32_t);
} SJpegData;

typedef struct IMAGE_DATA
{
unsigned char *pixels;
long len;
long width;
long height;
}ImageData;

/*------------------------------------------------------------------------------
* Exported functions
*------------------------------------------------------------------------------*/

extern uint32_t JpegData_Init( SJpegData* pData );
extern uint32_t JpegData_SetSource( SJpegData* pData, uint8_t* pucSrc, uint32_t dwSrcLength );

extern uint32_t JpegData_SetDestination( SJpegData* pData, uint8_t* pucDst, uint32_t dwDstLength );
extern uint32_t JpegData_SetDimensions( SJpegData* pData, uint32_t dwWidth, uint32_t dwHeight, uint32_t dwBPP );
extern uint32_t JpegData_SetParameters( SJpegData* pData, uint32_t dwQuality, EJpegInput eInput, EJpegMethod eMethod );
extern uint32_t JpegData_SetCallback( SJpegData* pData, uint32_t (*cbk)( uint8_t*, uint32_t, uint32_t, uint32_t ));
extern uint32_t ijg_compress( SJpegData* pData );
extern uint32_t ijg_compress_raw_no_padding( SJpegData* pData );
extern uint32_t ijg_decompress( SJpegData* pData );



libjpeg.c
CODE
// Функция декодирования
extern uint32_t ijg_decompress(SJpegData* pData)
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
uint32_t dwSourceLength;
int row_stride;
long counter=0;

JSAMPROW aLines[2];
assert( pData != NULL );
cinfo.err=jpeg_std_error( &jerr );
jpeg_create_decompress( &cinfo );
dwSourceLength=pData->dwSrcLength;
jpeg_mem_src( &cinfo, (uint8_t*)pData->pucSrc, dwSourceLength );
jpeg_read_header( &cinfo, TRUE );
cinfo.dct_method = pData->eMethod;
jpeg_start_decompress( &cinfo );
row_stride = cinfo.output_width * cinfo.output_components;

imageData = malloc(sizeof(ImageData));
imageData->width = cinfo.output_width;
imageData->height = cinfo.output_height;
imageData->len = cinfo.output_width * cinfo.output_height * cinfo.output_components;
imageData->pixels = malloc(imageData->len);
memset(imageData->pixels, 0, imageData->len);

aLines[0] = (JSAMPROW)malloc(sizeof(JSAMPLE) * row_stride);
for (;cinfo.output_scanline < cinfo.image_height;)
{
jpeg_read_scanlines( &cinfo, aLines, 1 );
memcpy(imageData->pixels+counter, aLines[i], row_stride);
counter += row_stride;
}

(*pData->cbk)(imageData->pixels, imageData->len, imageData->width, imageData->height);

jpeg_finish_decompress( &cinfo );
jpeg_destroy_decompress( &cinfo );

free(imageData->pixels);
free(imageData);
free(aLines[0]);
return 0;
}


main.c
Код
  SJpegData pData;
......
  JpegData_Init(&pData);  
  JpegData_SetSource(&pData, (uint8_t*)data, len);
  JpegData_SetDimensions(&pData, 1280, 800, 24);
  JpegData_SetParameters(&pData, 12, JPG_DATA_YCbCr, JPG_METHOD_IFAST);
  JpegData_SetCallback(&pData, &DataImage);
  ijg_decompress(&pData);
scifi
Цитата(Александр П. @ Mar 11 2014, 09:43) *
Работает, но очень медленно (~ 1 кадр в сек)

Почему вы решили, что это медленно? Может быть, это наоборот очень быстро?
Александр П.
OK, scifi. Скажите, как понять быстро это или медленно. CPU SAMA5D3

В настройках декодера может какие-то ньюансы есть?
aaarrr
Цитата(Александр П. @ Mar 11 2014, 09:53) *
CPU SAMA5D3

Тогда медленно даже для развесистого libjpeg. Процессор правильно инициализирован (тактирование, кэш)?
DpInRock
Да не так чтоб уж кардинально медленно.
Даже если кэши не включены - ну вдвое ускорится. Но чего-то реактивного - не будет.
---
Чисто по 400 MHz. ПРограммно получалось выводить на экран видео MJPEG не помню точно типа 170х170 с USB камеры герц 10-15. Если бы даже только одну задачу оставить - принципиально лучше бы не стало.
Александр П.
Кэши включены
Код
#if defined (ddram)
    MMU_Initialize((uint32_t *)0x30C000);
    CP15_EnableMMU();
    CP15_EnableIcache();
    CP15_EnableDcache();
#endif


Если поставить linux с примером, то в браузере того самого примера отрисовка идет с приличной скоростью. (IP камера)
У меня приложение без операционной системы. Данные с камеры получаю с хорошей скоростью, отрисовка на экране тоже быстро, а вот декодирование...
Как тогда из под линукса это все быстро отрисовывается. Если я правильно понимаю, то в линуксе так же производится декодирование в RGB, ибо как иначе на экранчик все это вывести?
DpInRock
Осталось узнать в каком формате передает камера. Вряд ли МJPEG?

Не используют обычно MJPEG из-за трафика
-----
Мож 1 кадр в секунду - только ключевые кадры показывает, а все остальное выбрасывает. Декодеры, они умеют мусор выкидывать...
Александр П.
DpInRock, камера передает отдельные JPEGи, используя заголовки и разделители для каждого кадра. Но это не mjpeg. Здесь я разбираю посылку и выделяю из нее сам кадр. На этом этапе проблем нет, ~15 кадров в секунду, что вполне достаточно. Я сам обрабатываю каждый байт полученый с камеры, поэтому никаких ключевых кадров здесь быть не может. Так же нет никакого межкадрового сжатия и прочих плюшек mjpeg

Друзья, может какой-то декодер другой посоветуете? Сначало пробовал picjpeg. Там вообще все уныло. Или какой-то принципиально другой подход. Я имею в памяти 100-150 kb jpega. Мне нужно вывести его на экран, понимающий формат RGB, и делать это надо хотя бы 10 раз в секунду.
jcxz
Цитата(Александр П. @ Mar 11 2014, 13:58) *
Или какой-то принципиально другой подход. Я имею в памяти 100-150 kb jpega. Мне нужно вывести его на экран, понимающий формат RGB, и делать это надо хотя бы 10 раз в секунду.

Чем очевидный подход не устраивает: добавить памяти и распаковать JPEG предварительно в raw в эту память и хранить в ней и выводить из неё?
DpInRock
MJEG - это РОВНО передача КАЖДОГО кадра в формате JPEG. Без ничего лишнего.

Камера обычно настраивается. Разрешение, кодировка.
У меня декодер урезанный и оптимизированный прямо для моего личного экрана. Т.е. вырезано все, оптимизировано все.

И чисто по ИМХО - любые другие способы сжатия - они лучше в плане быстродействия, хотя и сложнее.
Кстати, не так давно товарищу помогал как раз в линуксе на гигагерцовом проце наладить камеру, правда, USB.
Вот еще больший отстой увидел... И как бы не удивился.

А вот тут раз вы говорите, что линукс бодро рисует, то у меня сомнение и закралось. В типе кодировки.(Т.е. вы настраиваете на джпег, а линукс не будь дураком - на что-то более нормальное).
Александр П.
jcxz, а я разве не так делаю сейчас. Памяти, вот посмотрите...
SAMA5D3

Цитата
У меня декодер урезанный и оптимизированный прямо для моего личного экрана. Т.е. вырезано все, оптимизировано все.

Т.е вы работаете с изображениями намного меньше моего?
Если я запрашиваю с камеры область 640x400, то декодирование одного кадро проходит за 90 ms, т.е примерно 10 кадров я получаю. Вот я и пытаюсь понять, аппаратные это ограничения, или же программные.
jcxz
Цитата(Александр П. @ Mar 11 2014, 14:24) *
jcxz, а я разве не так делаю сейчас. Памяти, вот посмотрите...

Я же не телепат - Вы вашу задачу не описали.
Значит у Вы получаете картинки с камеры. Так бы и написали.
DpInRock
Цитата
проходит за 90 ms,

Вот это похоже на правду. Т.е. - на мой взгляд - нормально.
Скорее всего, улучшить можно, но не кардинально (не меняя кодировки кадра).

(У меня разрешение меньше, но на декодирование и отображение я выделял только 1\4 ресурсов 400 мегагерцового процессора. Хотя и камера как таковая была так себе. Да и USB - FS только.).
Александр П.
Может быть TFT дисплеи с аппаратными JPEG декодерами бывают? Кто-нибудь работал с такими?
aaarrr
Цитата(Александр П. @ Mar 11 2014, 17:14) *
Может быть TFT дисплеи с аппаратными JPEG декодерами бывают? Кто-нибудь работал с такими?

Процессоры с декодерами бывают, таких много. Про TFT дисплеи с JPEG входом не слышал.

У Вас какая-то явная нестыковка: если 640x400 декодируется за 90мс (что нормально для libjpeg), то 1280x800 должен бы уложится в 360мс, а не секунду.
Александр П.
Цитата
1280x800 должен бы уложится в 360мс, а не секунду.

Да, Вы правы, так и есть. Декодируется за 310 ms. Есть тормоза в другом мест. Но, это только 3 кадра в сек (

Друзья, объясните, пожалуйста, как работают в таком случае фоторамки. Первый попавшийся пример
Там и экран 800x600, и поддержка mjpeg. У меня 800x600 декодируется ~180 ms. Неужели рамка отображает 5-6 кадров в сек?
aaarrr
У рамок аппаратные декодеры обычно.
blackfin
Цитата(Александр П. @ Mar 11 2014, 12:24) *
jcxz, а я разве не так делаю сейчас. Памяти, вот посмотрите...
SAMA5D3
Если я запрашиваю с камеры область 640x400, то декодирование одного кадро проходит за 90 ms, т.е примерно 10 кадров я получаю. Вот я и пытаюсь понять, аппаратные это ограничения, или же программные.

BF533 тратит на декодирование каждого JPEG пикселя в среднем 74.3 такта процессора.
Для процессора с частотой 533 МГц и кадра размером 1280*800 это дает среднее время декодирования кадра: 1280*800*74.3/533e6 = 0.14 сек.
Процессор SAMA5D3, как я полагаю, должен давать примерно такие же результаты, так что получить с этим процессором 10 кадров в секунду будет, видимо, невозможно.
Dron_Gus
NEON должен немного помочь.
_4afc_
Цитата(blackfin @ Mar 12 2014, 03:24) *
Процессор SAMA5D3, как я полагаю, должен давать примерно такие же результаты, так что получить с этим процессором 10 кадров в секунду будет, видимо, невозможно.


Возможно ускорение, если декодировать самому каждый блок 8х8 напрямую в видеопамять.
В библиотечных декодерах данные несколько раз перекопируются и перетасовываются.
Нам удалось ускорить в одном проекте библиотеку декодирования JPEG в 15!!! раз.
DpInRock
Цитата
NEON должен немного помочь.

У SAM5 нет неона.
Цитата
Нам удалось ускорить в одном проекте библиотеку декодирования JPEG в 15!!! раз.

Это просто говорит о качестве библиотеки. Не более.
Александр П.
Спасибо за ответы.

Да, NEONа нет на SAMA5D3.

Цитата
Возможно ускорение, если декодировать самому каждый блок 8х8 напрямую в видеопамять.
В библиотечных декодерах данные несколько раз перекопируются и перетасовываются.
Нам удалось ускорить в одном проекте библиотеку декодирования JPEG в 15!!! раз.


_4afc_, а какую библиотеку Вы правили?

Цитата
Это просто говорит о качестве библиотеки. Не более.


DpInRock, Вы полагаете с libjpeg такой фокус не пройдет?

Друзья, как вы считаете, получу ли я желаемый результат, если буду запрашивать с камеры H.264 и декодировать его?
DpInRock
264 - Легко. В смысле, получите результат, если таки одолеете.

Чисто по аналогии. Древние КПК на 400 мегагерцовых процессорах без всяких аппаратных декодеров показывали кино худо-бедно. Под виндами мобильными.


Копейкин
Цитата
Древние КПК на 400 мегагерцовых процессорах...

Они работали с разрешением 320х240 и то притормаживали.
DpInRock
У кого притормаживали. А у меня до сих пор летают.
_4afc_
Цитата(Александр П. @ Mar 12 2014, 08:35) *
_4afc_, а какую библиотеку Вы правили?


Было взято 3 исходника: Чеха, Китайца и jpegsr8b.

На чехе отработали ввод вывод. Затем расписали jpegsr8b убрав лишние if на те форматы, что наша камера не генерила,
расписали DCT чтоб компилился без стека и ввод/вывод был в ОЗУ камня.
Насколько я помню от китайцев был какой-то толк в уменьшении количества умножений в DCT.

Конкретно jpegsr8b - ускорился в 12.5 раз, а общее ускорение от Чеха до релиза - 15.5 раз.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.