2012-01-21 4 views
2

У меня есть фильтр исходного источника DirectShow, написанный на Delphi 6 с помощью библиотеки компонентов DSPACK. Фильтр работает нормально во время вызова Skype, если клиент Skype использует фильтр: не 5.x или новее. С 5.x клиент Skype становится очень вялым до тех пор, пока он не зависает, а затем я получаю множество плохих сбоев, включая предупреждения предотвращения выполнения данных и типичное диалоговое окно Microsoft «эта программа разбилась». Иногда он срабатывает немедленно, в других случаях он вылетает примерно через 30 секунд или более.Мой фильтр DirectShow выдает Skype 5.x во время разговора. Работает нормально в 4.x, Редактирование графа и другие программы

можно также запустить видеофильтр без ошибок в следующих контекстах:

  • С Skype 5.x в окне предварительного просмотра видео фильтра, который вы видите при выборе видео устройства для использования с Skype (не в вызове, а на странице диалога выбора параметров видео).
  • Skype 4.x клиент (отлично работает в режиме разговора и отъезда)
  • Graph Edit
  • DSPACK TVideoWindow экземпляра
  • Другие программы, которые используют веб-камера питается

Я сделал некоторые исследования на сети и нашел довольно много жалоб на Skype 5.x и аварий. Потоки, которые я прочитал, предложили загрузить бета-версию 5.7. Я пробовал это, и это не помогло. Он работает немного лучше, но затем все еще падает.

Как тест на голые кости, я изменил свой метод FillBuffer(), чтобы просто поставить статическую растровую карту, которую загружаю при запуске вместо внешнего видеопотока, который я обычно передаю в Skype. Он все еще падает. Кроме того, я даже попробовал запустить DLL-фильтр с фильтром push-файлов с помощью FastMM4, чтобы выполнить полную проверку памяти с каждым вызовом FillBuffer() и вызовом, который доставляет образец мультимедиа к выходу ниже по течению. Никаких ошибок.

Поскольку Skype, очевидно, работает с другими драйверами веб-камеры, или в Интернете будет огромный протест, что может сделать мой фильтр, возможно, он не нравится?

ОБНОВЛЕНИЕ: При дальнейшем тестировании я столкнулся с чем-то странным. Первоначально, вызов GetMediaType() в моем фильтре имел 4 формата. Я сбил это до 1 формата: 24-бит с сжатием, установленным в BI_RGB, так как это то, что я получаю извне, а затем передаю Skype. Сразу же я начал быстро сбиваться с Skype, когда он запускает проверку фильтра DirectShow после входа в систему, и сбой произошел во время моего вызова GetStreamCaps(). Поскольку у Skype есть код отладки, я тщательно добавил сообщения трассировки на мой вызов GetStreamCaps() после каждой строки и обнаружил, что это происходит во время моей первой попытки получить доступ к его переменной формата носителя (см. Ниже). Похоже, что у меня возникли проблемы с доступом к области памяти, которую Skype передает моему фильтру DirectShow. Почему наличие только одного медиаформата, предлагаемого в сравнении с предыдущими 4, делает ошибки более быстрыми, неизвестно.

Это чисто предположение с моей стороны, но возможно ли, что какая-то странная ошибка доступа к области памяти возникает между Skype и моим фильтром? Тот факт, что Skype иногда сообщал об ошибке предотвращения выполнения данных до того, как я дошел до начала вызова, наряду с другими общими авариями, заставляет задуматься, происходит ли что-то экзотическое. Ошибка DEP возникает при попытке записи в область, отмеченную как блок кода. Это как если бы указатель Skype переходил ко мне, указывая на какое-то странное или защищенное место, на которое я не могу писать.

Чтобы повторить, теперь ошибка возникает 100% каждый раз, когда Skype обращается к моему фильтру DirectShow при вызове GetStreamCaps(), прежде чем я когда-нибудь начну инициировать вызов, или я даже могу получить доступ к экрану выбора видеоустройства. Вот соответствующий фрагмент кода:

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; 

UPDATE 2: Существует что-то случилось с моим кодом, но я не знаю, что. Graph Edit не вызывает GetStreamCaps(), как это делает Skype. Я добавил еще несколько инструкций трассировки, и оказалось, что в вышеприведенном коде объект типа мультимедиа, возвращенный вызовом 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; 

ответ

1

Много информации, но я мог бы ухватиться следующее:

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, равно нулю.

+0

Да, это то, что я сказал в конце сообщения. Я пытаюсь понять, почему это происходит сейчас. Есть что-то о времени GetStreampCaps() против GetMediaType() или CheckMediaType(), которое происходит до того, как я или DSPACK инициализируют .pbFormat. Есть ли у вас какие-либо идеи о том, что может быть неправильным, или образец кода, который я мог бы посмотреть, что может помочь? –

+0

Вы создали этот тип носителя. Зачем вам писать в поле «NULL»? Просто выделите его и правильно инициализируйте, создайте там хороший тип носителя. –

+0

«Просто выделите его и правильно инициализируйте ...». Это проблема. Мне нужно знать, как и особенно когда это делать. Я посмотрел на код DSPACK, и вызов SetMediaType() - это единственное место, где установлен Fmt.pbFormat. Это происходит только при попытке подключения к выходу источника во время фазы согласования соединения. Skype вызывает GetMediaType(), а затем GetStreamCaps() до того, как SetMediaType() когда-либо называется. Поэтому Fmt.pbFormat - это NIL в то время. Нужно ли устанавливать Fmt.pbFormat на какое-то произвольное значение, чтобы просто поддерживать Skype? –