| Предыдущая тема :: Следующая тема |
| Автор |
Сообщение |
AndrеySol Активный
Зарегистрирован: 27.02.2007 Сообщения: 57
|
Добавлено: Пт Апр 20, 2007 8:42 am Заголовок сообщения: Воспроизведение видео и закрытие графа. |
|
|
Собираю граф через RenderFile для видео-файла, запускаю, появляется окно видео, все идет ОК.
Если вызвать
| Код: | pMediaControl->Stop();
pGraphBuilder->Release(); |
воспроизведение останавливается, Release() возвращает ошибку "Неверная функция" и окно видео остается видимым. Если сразу сделать повторно Release() то все происходит как положено - окно видео уничтожается и возвращаемое значение "Операция завершена успешно".
Но самое непонятное - несколько дней назад все было прекрасно, окно видео уничтожалось после первого вызова Release(). Никаких изменений в код своей проги за эти дни не вносил.
Что за беда ? В чем дело ?
На всякий случай: WinXP Pro SP2. |
|
| Вернуться к началу |
|
 |
AndrеySol Активный
Зарегистрирован: 27.02.2007 Сообщения: 57
|
Добавлено: Сб Апр 21, 2007 3:27 pm Заголовок сообщения: |
|
|
Нашел в чем дело - виноват оказался фильтр переделанный по рекомендациям из статьи "Руководство по созданию Transform-фильтра", который позволяет регистрировать графы в ROT. После отмены регистрации этого фильтра все стало ОК.
Интересно в чем причина такого поведения ?
Модератору: как-нить можно этот момент обсудить с автором статьи ? |
|
| Вернуться к началу |
|
 |
WondeRu Главвред :)

Зарегистрирован: 30.10.2006 Сообщения: 199 Откуда: Самара
|
Добавлено: Вс Апр 22, 2007 2:30 pm Заголовок сообщения: |
|
|
| AndrеySol писал(а): | | Модератору: как-нить можно этот момент обсудить с автором статьи ? |
Сообщил ему  |
|
| Вернуться к началу |
|
 |
Vlafy Новенький
Зарегистрирован: 22.04.2007 Сообщения: 8 Откуда: Сосновый Бор
|
Добавлено: Вс Апр 22, 2007 3:10 pm Заголовок сообщения: |
|
|
| AndrеySol писал(а): | Нашел в чем дело - виноват оказался фильтр переделанный по рекомендациям из статьи "Руководство по созданию Transform-фильтра", который позволяет регистрировать графы в ROT. После отмены регистрации этого фильтра все стало ОК.
Интересно в чем причина такого поведения ?
Модератору: как-нить можно этот момент обсудить с автором статьи ? |
Обсудить можно, почему же нет
Собственно, причина такого поведения в том, что вы не убили все фильтры, входящие в граф.
Вообще, рекомендуется строить граф вручную (т.е. с добавлением всех нужных фильтров по их GUID), а потом перед уничтожением графа убивать все фильтры. Особенно это важно, если граф строится в программе многократно. Если где-то что-то недоубить, то даже при внешне правильной работе может быть большая утечка памяти. Я сам недавно на эти грабли наступил.
Либо если вы хотите строить граф автоматически, то надо опять же перед убиванием графа сделать поиск всех фильтров в нём и убить сначала фильтры. Только при этом надо быть готовым к тому, что в графе могут оказаться ненужные фильтры. Например, кодек-пак K-Lite славится внедрением во все графы некоторых своих фильтров, что зачастую приводит к чёрному экрану и прочим проблемам. И даже если на вашем компьютере всё будет работать, то на другом может и глючить. |
|
| Вернуться к началу |
|
 |
Alan Участник
Зарегистрирован: 11.04.2007 Сообщения: 13
|
Добавлено: Сб Май 05, 2007 12:34 am Заголовок сообщения: |
|
|
У меня похожая проблема, собираю простой граф
Video Capture Source -> YUV9 Converter -> Video Renderer.
Потом граф останавливаю, удаляю и собираю заново. А ActiveMovie Window остается на экране (окно черное, отрисовка прекращается).
Сначала подумал (точнее здесь прочитал, ) про "лишние" фильтры, посмотрел в GraphEdit'e все в порядке, ничего лишнего.
Пробовал убивать каждый фильтр вручную, пробовал вот так: | Код: | pFilterChain->StopChain(pVideoCaptureFilter, pRenderFilter);
pFilterChain->RemoveChain(pVideoCaptureFilter, pRenderFilter); | ничего не помогает.
Что еще, кроме не удаленных из графа фильтров, может приводить к такой ошибке? |
|
| Вернуться к началу |
|
 |
Vlafy Новенький
Зарегистрирован: 22.04.2007 Сообщения: 8 Откуда: Сосновый Бор
|
Добавлено: Сб Май 05, 2007 12:46 pm Заголовок сообщения: |
|
|
Если остаётся окно просмотра, то это однозначно говорит о том, что остаётся неубитым Video Renderer. Можете попробовать в графэдите это проверить.
Что-то вы неправильно делаете всё-таки. |
|
| Вернуться к началу |
|
 |
Alan Участник
Зарегистрирован: 11.04.2007 Сообщения: 13
|
Добавлено: Пт Май 11, 2007 11:48 pm Заголовок сообщения: |
|
|
Проверил и перепроверил все! Video Renderer в GraphEdit'e исчезает, а ActiveMovie Window остается на экране! (Пробовал вариант без регистрации графа в ROT - ничего не меняется)
Удаляю фильтр так: | Код: | hr = pGraphBuilder->RemoveFilter(pRenderFilter);
hr = pRenderFilter->Release(); |
Вообще, я не совсем понимаю, как один фильтр может повлиять на возможность удаления другого?
Если метод Release срабатывает со второго раза, значит где-то остается "неучтенный" указатель на этот фильтр?
Насколько я понял, фильтры при соединении обмениваются указателями на соединяемые пины, но при разорванном соединении (если можно об этом судить по отсутствию связей в GraphEdit) фильтры никак друг с другом не связаны...
Если не сложно, объясните как правильно удалять фильтры из графа? |
|
| Вернуться к началу |
|
 |
Vlafy Новенький
Зарегистрирован: 22.04.2007 Сообщения: 8 Откуда: Сосновый Бор
|
Добавлено: Вс Май 20, 2007 11:50 pm Заголовок сообщения: |
|
|
Да в общем-то всё правильно, так и надо удалять фильтры. Но если один фильтр получал какой-то интерфейс от другого фильтра и не освобождал его, тогда в памяти будет болтаться экземпляр фильтра, пока другие его не освободят.
Чтобы найти такую ошибку, надо видеть всю программу целиком. Я тоже долго возился с удалением фильтров из графа и в результате всё-таки победил эту проблему. |
|
| Вернуться к началу |
|
 |
Alan Участник
Зарегистрирован: 11.04.2007 Сообщения: 13
|
Добавлено: Пн Май 21, 2007 4:43 pm Заголовок сообщения: |
|
|
Вот так выглядит моя программа:
| Код: | IGraphBuilder *pGraphBuilder;
IBaseFilter *pVideoCaptureFilter;
IBaseFilter *pconverterFilter;
IBaseFilter *pRenderFilter;
IMediaControl *pMediaControl; |
Функции GetFilter, GetPin и ConnectFilters я, практически без изменений, позаимствовал из DS SDK и на РСДН
| Код: | HRESULT GetFilter(CComBSTR& bstrFilterName, IBaseFilter **pFilter, REFCLSID clsidDeviceClass)
{
HRESULT hr;
CComQIPtr<ICreateDevEnum, &IID_ICreateDevEnum> spSysDevEnum;
hr = spSysDevEnum.CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC);
if (SUCCEEDED(hr)){
CComPtr<IEnumMoniker> pEnum;
hr = spSysDevEnum->CreateClassEnumerator(clsidDeviceClass, &pEnum, 0);
if (hr == S_OK){
CComPtr<IMoniker> pMoniker;
ULONG cFetched;
while (SUCCEEDED(pEnum->Next(1, &pMoniker, &cFetched)))
{
if (!pMoniker){
hr = E_FAIL;
break;
}
CComQIPtr<IPropertyBag> pPropBag;
hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag);
if SUCCEEDED(hr){
CComVariant varCurFilterName;
varCurFilterName.vt = VT_BSTR;
pPropBag->Read(L"FriendlyName", &varCurFilterName, 0);
if (bstrFilterName == varCurFilterName.bstrVal){
pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**) pFilter);
return S_OK;
}
}
pMoniker = NULL;
}
}
}
return E_FAIL;
}
HRESULT GetPin(PIN_INFO* pPinInfo, CComPtr<IPin>& pPin)
{
HRESULT hr;
if (pPinInfo->pFilter){
CComPtr<IEnumPins> pEnumPins;
ULONG cFetched;
hr = pPinInfo->pFilter->EnumPins(&pEnumPins);
while(pEnumPins->Next(1, &pPin, &cFetched) == S_OK)
{
PIN_INFO piPinInfo;
hr = pPin->QueryPinInfo(&piPinInfo);
if (SUCCEEDED(hr)){
if (piPinInfo.dir == pPinInfo->dir && piPinInfo.achName[0] != L'~'){
CComPtr<IPin> pConnectedPin;
hr = pPin->ConnectedTo(&pConnectedPin);
if (hr == VFW_E_NOT_CONNECTED || !pConnectedPin){
hr = S_OK;
break;
}
}
}
pPin = NULL;
}
}
else {
hr = E_INVALIDARG;
}
return hr;
}
HRESULT ConnectFilters(IBaseFilter* pSourceFilter, IBaseFilter* pReceiveFilter, IGraphBuilder* pGraphBuilder)
{
HRESULT hr;
CComPtr<IPin> pOutputPin;
CComPtr<IPin> pInputPin;
PIN_INFO piPinInfo = {pSourceFilter, PINDIR_OUTPUT, {0}};
hr = GetPin(&piPinInfo, pOutputPin);
if (SUCCEEDED(hr)){
piPinInfo.pFilter = pReceiveFilter;
piPinInfo.dir = PINDIR_INPUT;
hr = GetPin(&piPinInfo, pInputPin);
hr = pGraphBuilder->Connect(pOutputPin, pInputPin);
}
return hr;
} |
Построение графа: | Код: | HRESULT BuildCaptureGraph()
{
CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,
IID_IGraphBuilder, (void**)&pGraphBuilder);
GetFilter(CComBSTR("Ewclid® VideoSynth Source"), &pVideoCaptureFilter,
CLSID_VideoInputDeviceCategory);
GetFilter(CComBSTR("Ewclid® YVU9 converter"), &pconverterFilter,
CLSID_LegacyAmFilterCategory);
GetFilter(CComBSTR("Video Renderer"), &pRenderFilter,
CLSID_LegacyAmFilterCategory);
pGraphBuilder->AddFilter(pVideoCaptureFilter, L"Ewclid® VideoSynth Source");
pGraphBuilder->AddFilter(pconverterFilter, L"Ewclid® YVU9 converter");
pGraphBuilder->AddFilter(pRenderFilter, L"Video Renderer");
ConnectFilters(pVideoCaptureFilter, pconverterFilter, pGraphBuilder);
ConnectFilters(pconverterFilter, pRenderFilter, pGraphBuilder);
pGraphBuilder->QueryInterface(&pMediaControl);
pMediaControl->Run();
hr = AddToRot(pGraphBuilder, &dwRegister);
return S_OK;
} |
и удаление графа: | Код: | void ReleaseGraph()
{
pMediaControl->Stop();
hr = pGraphBuilder->RemoveFilter(pRenderFilter);
hr = pGraphBuilder->RemoveFilter(pconverterFilter);
hr = pGraphBuilder->RemoveFilter(pVideoCaptureFilter);//до этого момента hr = S_OK
hr = pRenderFilter->Release();//здесь счетчик ссылок равен 1
hr = pconverterFilter->Release(); //здесь счетчик ссылок равен 3
hr = pVideoCaptureFilter->Release();//здесь счетчик ссылок равен 1
hr = pMediaControl->Release();//S_FALSE
hr = pGraphBuilder->Release();//S_OK
} |
После этого ActiveMovie window становится черным и убирается только после следующего pRenderFilter->Release(); Я так чувствую, самое правильное мне сейчас за книжки по отладке и по COM взяться  |
|
| Вернуться к началу |
|
 |
AndrеySol Активный
Зарегистрирован: 27.02.2007 Сообщения: 57
|
Добавлено: Пт Май 25, 2007 1:02 am Заголовок сообщения: |
|
|
| Не очень понятна тема с ручным удалением каждого фильтра - у меня прога воспроизводит список видео-клипов 15-20 штук, при этом для каждого строится граф а затем убивается обычным pGraphBuilder->Release() - проблем нет. |
|
| Вернуться к началу |
|
 |
Alan Участник
Зарегистрирован: 11.04.2007 Сообщения: 13
|
Добавлено: Сб Май 26, 2007 12:45 am Заголовок сообщения: |
|
|
А у меня есть. Если просто сделать pGraphBuilder->Release(), фильтры остаются в памяти, со всеми вытекающими в виде черного ActiveMovie Window и т.д. Наверное что-то не так в процедуре получения фильтра или связывания фильтров между собой, потому как результат не зависит от набора фильтров или получаемых от них интерфейсов.
А можете показать как вы добавляете фильтры в граф и соединяете их? |
|
| Вернуться к началу |
|
 |
AndrеySol Активный
Зарегистрирован: 27.02.2007 Сообщения: 57
|
Добавлено: Сб Май 26, 2007 12:37 pm Заголовок сообщения: |
|
|
Да в общем все так-же как и в вашем примере.
Только для воспроизведения (рендеринга) использую не ручное а автоматическое построение графа, а ручное - при сборке графа конвертирования. В обоих случаях все нормально.
Кстати попробуйте для теста убрать
hr = AddToRot(pGraphBuilder, &dwRegister);
и посмотреть как будет ? |
|
| Вернуться к началу |
|
 |
Vlafy Новенький
Зарегистрирован: 22.04.2007 Сообщения: 8 Откуда: Сосновый Бор
|
Добавлено: Вт Июн 26, 2007 8:19 pm Заголовок сообщения: |
|
|
Автоматический рендер плох тем, что сильно зависит от фильтров, установленных в системе, у которых высокий мерит. Такие фильтры будут в любом случае грузиться в граф. На этом "основан" нередкий глюк с фильтрами из K-Lite, проявляющийся в чёрном экране вместо картинки. Причём, на одном компе может всё работать, а на другом - нет. Поэтому лучше делать ручную сборку графа.
Alan, у меня сейчас совсем мало времени, напишите на мыло, может быть удастся совместно найти причину ваших проблем. |
|
| Вернуться к началу |
|
 |
Vlafy Новенький
Зарегистрирован: 22.04.2007 Сообщения: 8 Откуда: Сосновый Бор
|
Добавлено: Сб Июл 07, 2007 3:35 pm Заголовок сообщения: |
|
|
Я тут столкнулся с аналогичной проблемой - остаётся окно ActiveMovie Window. Стал рыться в своих исходниках других программ, и нашёл такое решение:
| Код: |
IVideoWindow *pVideoWindow;
...
if (pVideoWindow) {
pVideoWindow->put_Visible(0);
pVideoWindow->put_Owner(NULL);
} |
Кроме того, полезно перед Release() удалять каждый фильтр из графа с помощью IFilterGraph->RemoveFilter(). И ещё есть полезная ф-ция CoFreeUnusedLibraries(), которая отцепляет неиспользуемые библиотеки. |
|
| Вернуться к началу |
|
 |
Alan Участник
Зарегистрирован: 11.04.2007 Сообщения: 13
|
Добавлено: Пн Июл 09, 2007 7:15 pm Заголовок сообщения: |
|
|
Две недели был в отпуске, за это время полностью переписал все функции связанные с созданием и соединением фильтров (без смарт-поинтеров, все делаю вручную). Собственно это и решило проблему, теперь все удаляется/закрывается как и должно.
У меня ошибка была либо в процедуре выделения неподключенного пина, либо в процедуре соединения фильтров.
Я так понимаю, put_Visible(0) просто закрывает ActiveMovie Window, а фильтр при этом все равно повисает в памяти.
В общем большое всем спасибо, когда точно определю в чем была проблема - напишу, может кому пригодится. |
|
| Вернуться к началу |
|
 |
|
|
|
|
|
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете голосовать в опросах
|
|
|
|