Delphi 6 DirectShow过滤器中的渲染图像中不会出现对TBitmap的更改,并会生成大量软页面错误 [英] Changes to TBitmap do not appear in rendered image in Delphi 6 DirectShow filter and generates lots of soft page faults

查看:185
本文介绍了Delphi 6 DirectShow过滤器中的渲染图像中不会出现对TBitmap的更改,并会生成大量软页面错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个用DSPACK组件库写的Delphi6 DirectShow过滤器(推送源视频过滤器)。我有一个简单的代码修改位图,然后将修改的位图输出到我的FillBuffer()调用中的目标媒体示例真正令人烦恼的问题。代码如下所示。

正如您所看到的,它只是两个简单的循环,它们使用Byte指针遍历24位位图中的RGB值。此代码在非DirectShow测试应用程序中正常工作。但是,在我的DirectShow过滤器中,无论使用哪个值,都不会在渲染的位图中看到任何更改。你甚至可以看到一个测试线,我简单地设置每个字节为0.我仍然看到图像未修改。为了确保我没有幻影或损坏的位图对象,我添加了一行来在位图上打印一个简单的句子。更复杂的是,当这段代码运行时,我得到了成千上万个 soft 的每秒的页面错误,由任务管理器报告。如果我禁用此代码,则 soft 页面错误消失。什么可能导致代码做到这一点?我追踪了循环,并确实看到每行后的字节值更改值,但图像保持不变。



最后,如果有人知道一个快速的方法像素访问不使用Scanline我想知道。我追踪了TBitmap.Scanline并调用了FreeImage。我想尽可能减少内存分配。我无法使用GR32.TBitmap32,因为我使用的是Synopse的快速jpeg解码器,它不能用于TBitmap32对象。


$ b

更新:问题在于,在访问ScanLine属性之前,我没有将位图的 PixelFormat 属性设置为pf24Bit。有关详细信息,请参阅此主题:

 在主应用程序中快速执行像素修改代码,在Delphi 6 DirectShow过滤器中真的很慢程序brightnessTurboBoost(var clip:TBitmap; rangeExpansionPowerOf2:integer; shiftValue:Byte); 
var
p0:PByte;
x,y:整数;如果(rangeExpansionPowerOf2 = 0)和(shiftValue = 0)则
开始
,则
exit; //这些参数设置不会改变像素值。

for y:= 0 to clip.Height-1 do
begin
p0:= clip.scanline [y];

//由于
//单独的扫描行可能被填充以进行CPU对齐,因此不能只将整个缓冲区作为大块字节来执行。
for x:= 0 to(clip.Width - 1)* 3 do
begin
if rangeExpansionPowerOf2> = 1 then
p0 ^:= IntToByte((p0 ^ shl rangeExpansionPowerOf2)+ shiftValue)
else
p0 ^:= IntToByte(p0 ^ + shiftValue);

//测试擦图像(没有工作,仍然看图像)。
// p0 ^:= 0;
Inc(p0);
end;
end;

clip.Canvas.TextOut(10,10,'你好有人吗?');
end;


解决方案

> IMediaSample 将数据缓冲到 TBitmap 而不是向后?最有可能的事情,实际上比其他任何事情都更可能的是,你正在改变一个副本,而不是把这些改变反转回到你下游传递的缓冲区。另外,在处理的副作用(例如,在来回转换图像数据时过度的内存分配)上打印页面错误。

I have a Delphi6 DirectShow filter (push source video filter) written with the DSPACK component library. I am having a truly vexing problem with some simple code that modifies a bitmap before outputting the modified bitmap to the destination media sample in my FillBuffer() call. The code is shown below.

As you can see it is just two simple loops that use a Byte pointer to traverse the RGB values in a 24-bit bitmap. This code worked fine when it was in a non-DirectShow test application. However, in my DirectShow filter, I don't see any change in the rendered bitmap regardless of the values used. You can even see a test line where I simply set every Byte to 0. I still saw the image unmodified. To make sure I didn't have a phantom or damaged bitmap object I added a line to print a simple sentence on the bitmap. The sentence does show on the rendered bitmap.

Even more confusing is that when this code runs I get thousands of soft page faults per second, as reported by Task Manager. If I disable this code the soft page faults go away. What could cause the code to do this? I traced through the loop and did indeed see the Byte values change value after each line, but the image remains unaffected.

Finally, if anyone knows of a fast way to do pixel access without using Scanline I'd like to know. I traced through TBitmap.Scanline and it makes a call to FreeImage. I'd like to minimize memory allocations if I could. I can't use GR32.TBitmap32 because I am using Synopse's fast jpeg decoder and it won't work with TBitmap32 objects.

UPDATE: The problem was that I was not setting the bitmap's PixelFormat property to pf24Bit before accessing the ScanLine property. See this thread for more information: Pixel modifying code runs quick in main app, really slow in Delphi 6 DirectShow filter with other problems

procedure brightnessTurboBoost(var clip: TBitmap; rangeExpansionPowerOf2: integer; shiftValue: Byte);
var
   p0: PByte;
   x,y: Integer;
begin
   if (rangeExpansionPowerOf2 = 0) and (shiftValue = 0) then
       exit; // These parameter settings will not change the pixel values.

   for y := 0 to clip.Height-1 do
   begin
       p0 := clip.scanline[y];

       // Can't just do the whole buffer as a big block of bytes since the
       //  individual scan lines may be padded for CPU alignment.
       for x := 0 to (clip.Width - 1) * 3 do
       begin
           if rangeExpansionPowerOf2 >= 1 then
               p0^ := IntToByte((p0^ shl rangeExpansionPowerOf2) + shiftValue)
           else
               p0^ := IntToByte(p0^ + shiftValue);

// Test wiping the image (didn't work, still see image).
// p0^ := 0;
           Inc(p0);
       end;
   end;

   clip.Canvas.TextOut(10, 10, 'HELLO THERE IS THERE ANYONE THERE?');
end;

解决方案

So how exactly you are copying IMediaSample buffer data into TBitmap and than backward? The most likely thing, which is actually much more likely than anything else, is that you are changing a copy, and never flip the changes back to the buffer you deliver downstream. Additionally hitting page faults on the way as a side effect of the processing (such as excessive internal memory allocations while converting the image data back and forth).

这篇关于Delphi 6 DirectShow过滤器中的渲染图像中不会出现对TBitmap的更改,并会生成大量软页面错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆