Данные DirectFB из буфера памяти - PullRequest
5 голосов
/ 25 октября 2011

Мне нужен очень быстрый способ отображения буфера данных на экране. Сначала я попытался получить доступ к кадровому буферу Linux, и это оказалось довольно хорошим. Затем я узнал о DirectFB, и мне понравились дополнительные функции, которые он предоставляет (такие как быстрая memcpy, изменение размера изображений на лету, отсутствие необходимости в дополнительном коде и т. Д.). Но затем я наткнулся на загвоздку - все примеры для изображений, которые загружаются из файлов. Насколько я могу судить, нет примеров / руководств для его типа «DataBuffer». После просмотра документации и исходного кода мне удалось скомпилировать что-то вроде этого:

DFBSurfaceDescription sdsc;
DFBDataBufferDescription ddsc;
DFBDataBufferDescriptionFlags ddscf = (DFBDataBufferDescriptionFlags)DBDESC_MEMORY;
IDirectFBDataBuffer *dbuffer;
IDirectFBImageProvider *provider;

ddsc.flags = ddscf;
ddsc.file = NULL;
ddsc.memory.data = m_z;
ddsc.memory.length = 640*480;

DFBCHECK (DirectFBInit (&argc, &argv));
DFBCHECK (DirectFBCreate (&dfb));
DFBCHECK (dfb->SetCooperativeLevel (dfb, DFSCL_FULLSCREEN));
sdsc.flags = DSDESC_CAPS;
sdsc.caps  = (DFBSurfaceCapabilities)(DSCAPS_PRIMARY | DSCAPS_FLIPPING);
DFBCHECK (dfb->CreateSurface( dfb, &sdsc, &primary ));
DFBCHECK (primary->GetSize (primary, &screen_width, &screen_height));

DFBCHECK (dfb->CreateDataBuffer(dfb, &ddsc, &dbuffer));
DFBCHECK (dbuffer->CreateImageProvider(dbuffer, &provider));
DFBCHECK (provider->GetSurfaceDescription (provider, &sdsc));

DFBCHECK (dfb->CreateSurface( dfb, &sdsc, &fbwindow ));
DFBCHECK (provider->RenderTo (provider, fbwindow, NULL));
provider->Release (provider);

Итак, в основном я создаю DataBuffer из DFB, затем ImageProvider из DataBuffer и устанавливаю его для рендеринга на поверхности. Однако, когда я запускаю его, он выдает ошибку:

(#) DirectFBError [dbuffer->CreateImageProvider(dbuffer, &provider)]: No (suitable) implementation found!

Действительно ли метод не реализован? В настоящее время я использую DirectFB 1.4, из документации по API функция должна быть там. При этом, кто-нибудь знает, как получить буфер (char * 640 * 480 * 4 RGBA) из памяти для рендеринга в кадровый буфер с использованием DirectFB?

Спасибо.

Ответы [ 2 ]

7 голосов
/ 16 марта 2012

Может быть, немного поздно, чтобы помочь вам, но для кого-то еще, пытающегося это сделать, вот ответ.

Это на самом деле проще, чем вы думаете (с одной ошибкой) - я делаю точночто вы хотите, используя DirectFb 1.4.11.

Как только у вас есть основная поверхность, не беспокойтесь о DataBuffer.Создайте другую поверхность, используя флешку DSDESC_PREALLOCATED и ваш буфер в качестве предварительно выделенных данных.Затем Blit () данные вашей новой поверхности на первичной поверхности и Flip () первичной поверхности на экране.Единственное, что нужно, это то, что ваши данные должны быть в формате, понятном DirectFB: 32-битный RGBA - не один из них, а 32-битный ARGB - мне пришлось проанализировать буфер, чтобы поменять местами байты.

Пример кода:

  dsc.width = screen_width;
  dsc.height = screen_height;
  dsc.flags = DSDESC_HEIGHT | DSDESC_WIDTH | DSDESC_PREALLOCATED | DSDESC_PIXELFORMAT;
  dsc.caps = DSCAPS_NONE;
  dsc.pixelformat = DSPF_ARGB;
  dsc.preallocated[0].data = buffer;      // Buffer is your data
  dsc.preallocated[0].pitch = dsc.width*4;
  dsc.preallocated[1].data = NULL;
  dsc.preallocated[1].pitch = 0;

  DFBCHECK (dfb->CreateSurface( dfb, &dsc, &imageSurface ));
  DFBCHECK (primary->Blit(primary, imageSurface, NULL, 0, 0));
  DFBCHECK (primary->Flip(primary, NULL, DSFLIP_ONSYNC));

Если размер буфера не совпадает с размером и формой экрана, вы можете использовать вместо него StretchBlit (), чтобы изменить его размер.

Надеюсь, это поможет.

3 голосов
/ 31 марта 2014

Ответ выше от MartinP хорош, но работает, только если изображение не сжато. Я нашел эту тему, потому что хотел загрузить и декодировать / распаковать изображение png / jpeg непосредственно из памяти.

Вряд ли есть какая-либо полезная информация об этом, и я сам боролся с этим, но нашел, как это сделать. Хотя это старый вопрос, он может помочь тем, кто пытается сделать то же самое:

// Variables
DFBDataBufferDescription ddsc;
DFBSurfaceDescription sdsc;
IDirectFBDataBuffer *buffer;
IDirectFBImageProvider *image_provider;

// The surface that will contain the rendered image
IDirectFBSurface *surface;                      

// create a data buffer for memory
ddsc.flags = DBDESC_MEMORY;
ddsc.memory.data = data;
ddsc.memory.length = dataLength;
DFBCHECK(directFB->CreateDataBuffer(directFB, &ddsc, &buffer));

// Create the image provider, surface description and surface itself
DFBCHECK(buffer->CreateImageProvider(buffer, &image_provider));
DFBCHECK(image_provider->GetSurfaceDescription(image_provider, &sdsc));
DFBCHECK(directFB->CreateSurface(directFB, &sdsc, &surface ));

// Now render the image onto the surface
DFBCHECK(image_provider->RenderTo(image_provider, surface, NULL));

// Release 
image_provider->Release(image_provider);
buffer->Release(buffer);

Переменная data является указателем на массив беззнаковых символов, содержащих изображение (подсказка: вы можете создать такой массив с помощью 'xxd -i image.jpg> image.h'). длина данных - это целое число без знака с размером массива. Созданная поверхность может быть перетащена на экран, или, возможно, вы можете сразу «отобразить» поверхность дисплея.

...