来自内存缓冲区的 DirectFB 数据

Posted

技术标签:

【中文标题】来自内存缓冲区的 DirectFB 数据【英文标题】:DirectFB data from memory buffer 【发布时间】:2011-10-25 11:02:32 【问题描述】:

我需要一种在屏幕上显示数据缓冲区的非常快速的方法。我首先尝试访问 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);

所以基本上我从 DFB 创建一个 DataBuffer,然后从 DataBuffer 创建一个 ImageProvider 并将其设置为在表面上呈现。但是,当我运行它时,它会引发错误:

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

方法真的没有实现吗?我目前正在使用 DirectFB 1.4,从 API 文档中该函数应该在那里。话虽如此,有谁知道如何从内存中获取缓冲区(char*640*480*4 RGBA)以使用 DirectFB 渲染到帧缓冲区?

谢谢。

【问题讨论】:

【参考方案1】:

帮助您可能有点晚了,但为了其他尝试此操作的人的利益,这里有一个答案。

它实际上比你想象的要简单(有一个问题)——我正在做你想做的事,使用 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() 来调整它的大小。

我希望这会有所帮助。

【讨论】:

【参考方案2】:

上面来自 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 变量是指向包含图像的 unsigned char 数组的指针(提示:您可以使用 'xxd -i image.jpg > image.h' 创建这样的数组)。 datalength 是具有数组大小的无符号整数。创建的surface可以blit到屏幕上,或者您可以一次“渲染”到显示表面。

【讨论】:

这对我来说失败了,但我认为这是因为我将原始 ARGB 数据转储到了一个没有元信息的文件中,例如可能有的 PNG/JPEG/BMP 文件。我也必须尝试这个解决方案,这样我才能使我的应用程序更便携,谢谢分享。 这行得通。谢谢,我在ddsc.memory.data 中插入了一个 png 图像,它可以工作。

以上是关于来自内存缓冲区的 DirectFB 数据的主要内容,如果未能解决你的问题,请参考以下文章

处理来自内存缓冲区的视频流

来自内存缓冲区的 CreateProcess

解密Redis持久化翻译

计算机中的“溢出”到底是啥意思

裁剪像素缓冲区

nodejs buffer 内存泄漏问题