delphi - 在通话过程中,我的DirectShow筛选器使Skype 5.x崩溃。在4.x,Graph Edit和其他程序中运行良好

标签 delphi video directshow skype dspack

我有一个用Delphi 6和DSPACK组件库编写的DirectShow推源视频过滤器。只要使用该过滤器的Skype客户端不是5.x或更高版本,该过滤器在Skype调用期间即可正常运行。使用5.x,Skype客户端会变得非常缓慢,直到挂起为止,然后出现各种严重的崩溃,包括数据执行保护警告和典型的Microsoft“此程序已崩溃”对话框。有时它会立即崩溃,而另一些时间则是在通话约30秒或更长时间后崩溃。

我还可以在以下情况下运行视频过滤器,而不会出现错误:


在选择要与Skype一起使用的视频设备时在视频过滤器预览窗口中看到的Skype 5.x(不在通话中,而是在“视频选项”选择对话框页面上)。
Skype 4.x客户端(在呼入和呼出中完美运行)
图形编辑
DSPACK TVideoWindow实例
其他利用网络摄像头提要的程序


我在网上做了一些研究,并发现了很多有关Skype 5.x和崩溃的投诉。我读过的线程建议下载5.7 beta。我尝试过,但没有帮助。它运行得更好一些,但是仍然崩溃。

作为一个简单的测试,我更改了FillBuffer()方法,以提供在启动时加载的静态位图,而不是通常中继到Skype的外部视频流。它仍然崩溃。此外,我什至尝试将FastMM4设置为推入源过滤器DLL,以便对每个FillBuffer()调用以及将媒体样本传递到下游引脚的调用进行全内存扫描。没有任何错误。

由于Skype显然可以与其他网络摄像头驱动程序一起使用,或者网络上会有强烈的抗议声,我的过滤器可能会做什么,但它不喜欢这样做?

更新:经过进一步测试,我遇到了一些奇怪的事情。最初,我的过滤器中的GetMediaType()调用具有4种格式。我将其分解为1种格式:将压缩设置为BI_RGB的24位格式,因为这是我从外部收到的,然后传递给Skype。登录后,当它进行DirectShow筛选器扫描时,我立即开始从Skype遇到快速故障,并且该故障发生在我的GetStreamCaps()调用期间。由于Skype具有反调试代码,因此我在每一行之后都在我的GetStreamCaps()调用中精心添加了跟踪消息,并发现它是在我第一次尝试访问其媒体格式变量时发生的(请参阅下文)。看来我无法访问Skype传递给DirectShow筛选器的内存区域。为什么只提供一种媒体格式而不提供以前的4种媒体格式会使故障更快地发生是未知的。

这只是我的推测,但是在Skype和我的过滤器之间是否可能发生某种奇怪的内存区域访问特权错误? Skype偶尔会在我发起呼叫之前报告数据执行保护错误,以及其他一般崩溃,这一事实使我想知道是否发生了异常情况。当您尝试写入标记为代码块的区域时,发生DEP错误。就像Skype传递给我的指针所指向的是我无法写入的某个陌生或受保护的地方。

简而言之,现在在我每次发起呼叫之前,Skype每次在调用GetStreamCaps()时访问我的DirectShow过滤器时都会发生100%错误,或者甚至可以访问视频设备选择屏幕。这是相关的代码片段:

function TBCPushPinDesktop.GetStreamCaps(iIndex: Integer; out ppmt: PAMMediaType; out pSCC): HResult;
var
    pvi:PVIDEOINFOHEADER;
begin
  ppmt := CreateMediaType(@Fmt);

  pvi:=PVIDEOINFOHEADER(ppmt.pbFormat);

  // Error occurs at THIS statement, the first attempt to write to the memory area
  //  provided by Skype.
  pvi.bmiHeader.biCompression  := BI_RGB;

 .... SNIP ....
end;


更新2:我的代码有问题,但是我不知道是什么。 Graph Edit不会像Skype那样调用GetStreamCaps()。我添加了更多的跟踪语句,结果发现,在上面的代码中,由DSPACK CreateMediaType()调用返回的媒体类型对象具有NIL pbFormat字段,因此可以解释快速失败。如果有人知道获取正确配置的pbFormat字段所需的操作,请告诉我。以下是DSPACK中执行CreateMediaType()操作的代码:

  // this also comes in useful when using the IEnumMediaTypes interface so
  // that you can copy a media type, you can do nearly the same by creating
  // a CMediaType object but as soon as it goes out of scope the destructor
  // will delete the memory it allocated (this takes a copy of the memory)
  function  CreateMediaType(pSrc: PAMMediaType): PAMMediaType;
  var pMediaType: PAMMediaType;
  begin
    ASSERT(pSrc<>nil);

    // Allocate a block of memory for the media type
    pMediaType := CoTaskMemAlloc(sizeof(TAMMediaType));
    if (pMediaType = nil) then
    begin
      result := nil;
      exit;
    end;

    // Copy the variable length format block
    CopyMediaType(pMediaType,pSrc);
    result := pMediaType;
  end;

  //----------------------------------------------------------------------------
  // Copies a task-allocated AM_MEDIA_TYPE structure.
  //----------------------------------------------------------------------------
  procedure CopyMediaType(pmtTarget: PAMMediaType; pmtSource: PAMMediaType);
  begin
    //  We'll leak if we copy onto one that already exists - there's one
    //  case we can check like that - copying to itself.
    ASSERT(pmtSource <> pmtTarget);
    //pmtTarget^ := pmtSource^;
    move(pmtSource^, pmtTarget^, SizeOf(TAMMediaType));
    if (pmtSource.cbFormat <> 0) then
    begin
      ASSERT(pmtSource.pbFormat <> nil);
      pmtTarget.pbFormat := CoTaskMemAlloc(pmtSource.cbFormat);
      if (pmtTarget.pbFormat = nil) then
        pmtTarget.cbFormat := 0
      else
        CopyMemory(pmtTarget.pbFormat, pmtSource.pbFormat, pmtTarget.cbFormat);
    end;
    if (pmtTarget.pUnk <> nil) then  pmtTarget.pUnk._AddRef;
  end;

最佳答案

很多信息,但我可以掌握以下内容:

ppmt := CreateMediaType(@Fmt);
pvi:=PVIDEOINFOHEADER(ppmt.pbFormat);
// Error occurs at THIS statement, the first attempt to write to the memory area
//  provided by Skype.
pvi.bmiHeader.biCompression  := BI_RGB;


出现访问冲突的唯一原因是错误地初始化了.pbFormat。或者,否则,您可以正确地将其初始化为NULL,然后作为真实指针进行访问。

您的更新2表示NULL版本,或者.cbFormat在此处为零。

关于delphi - 在通话过程中,我的DirectShow筛选器使Skype 5.x崩溃。在4.x,Graph Edit和其他程序中运行良好,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8949964/

相关文章:

delphi - 我如何在Delphi中使用jclcompression,有例子吗?

ios - 能够为 iOS 调整表单大小的目的是什么?

javascript - 如何创建带有/视频背景的 HTML5 着陆页

C++ DirectShow 视频和音频捕获 - 开始

audio - 解复用 UDP/RTP 多节目传输流

c++ - IID_MediaControl 未声明的标识符

delphi - 如何重新创建一个检索对象最高元素的函数?

delphi - 为什么Delphi XE3给出 "E2382 Cannot call constructors using instance variables"?

video - 使用 FFMPEG 将 RTSP 流式传输到 HLS 流,使用较新的 FFMPEG 时出现错误

html - HTML5 视频标签上的黑框,仅在 Safari 7 (OSX Mavericks) 中