2013-08-15 2 views
1

비디오 파일에서 IMediaSample을 검색하기 위해 DirectShow 필터 그래프 작업 중입니다. 우리는 계약 개발자로부터 원래 구현을 받았다. 나는 왜이 코드가 내 개발 컴퓨터에서 작동하지만 다른 두 개의 테스트 서버에서는 작동하지 않는지 파악하려고 벽에 머리를 두드리는 소리를 쳤다.일부 컴퓨터에서는 DirectShow 필터 그래프가 완료되지 않습니다.

필자는 필터 그래프가 "깨진"컴퓨터에서 절대로 완료되지 않는다고 말할 수 있습니다. 나는 항상 IMediaEvent->WaitForCompletion() 전화에서 E_ABORT을받습니다. 그러나 "working"머신에서이 호출은 일반적으로 약 2 회 반복 후 S_OK을 반환합니다.

업데이트 : DirectShow Spy은 나를 위해 작동하지 않는 것 같습니다. 아마도 체인에 IMediaSample을 수집하기 위해 사용자 정의 된 등록되지 않은 CTransInPlaceFilter이 있었기 때문일 수 있습니다. 오류가 없지만 원격 그래프에 연결하려고하면 GraphEdit과 GraphStudio가 모두 멈 춥니 다. (< - 제안 메시지 펌핑이 해결로서) 나는 우리 CTransInPlaceFilter에 연결되는 MPEG-4 디코더에서 미디어 하위 유형을 얻을 수있었습니다 GraphStudio를 사용

. 내 컴퓨터에서는 MEDIASUBTYPE_YV12이지만 "깨진"컴퓨터에서는 MEDIASUBTYPE_IYUV입니다. 우리의 CTransInPlaceFilterCheckInputType 방법에서 우리는 MEDIASUBTYPE_RGB24만을 받아들이므로 하나 이상의 "마법 필터"가 그래프에 삽입되어 있다고 믿습니다.

업데이트 : Roman R.에게 감사드립니다. DirectShow Spy을 사용할 수있었습니다. 적어도 "부서진"기계에서. "작업"컴퓨터에서 액세스 위반이 발생하지만 필터 그래프가 빠르게 실행되어 해체되어 연결이 어려워집니다.

또한 MEDIASUBTYPE_IYUV을 처리 할 수있는 색 공간 변환기가 있음을 알게되었습니다. MEDIASUBTYPE_RGB24입니다. 그래프에 추가 했으므로 이제는 정확해야합니다.

DirectShow Spy는 필터 그래프로 이것을 보여줍니다 (나에게 완전한 모양) :

File Source -> MPEG Demux -> MPEG4 Decoder -> Color Space Converter -> CTransInPlaceFilter -> Null Render

그러나 IMediaEvent->WaitForCompletion() 호출은 결코 S_OK 반환되지 않으며, 필터 그래프가 영원히 실행됩니다. 그래서 지금 나는 무슨 일이 벌어지고 있는지에 대해 곤란하다. 오류 상태 나 기타 사항을 확인해야하는 것이 있습니까?

업데이트

: 나는 그래프의 필터를 열거하는 루프를 수정하고 자신의 상태 조회 : 그들은 "실행"상태에 모두

char debugString[512]; 

int count = 0; 
long EvCode; 
mediaFilter->SetSyncSource(NULL); 
hr = mediaControl->Run(); 

sprintf(debugString, "mediaControl->Run() %d", hr); 
DebugLog(debugString); 

while (!m_ThreadKill) 
{ 
    hr = mediaEvent->WaitForCompletion(200, &EvCode); 

    sprintf(debugString, "mediaEvent->WaitForCompletion() %d, %d", hr, count); 
    DebugLog(debugString); 
    count++; 

    IEnumFilters *pEnum = NULL; 
    IBaseFilter *pFilter; 
    ULONG cFetched; 

    graphBuilder->EnumFilters(&pEnum); 

    while(pEnum->Next(1, &pFilter, &cFetched) == S_OK) 
    { 
     FILTER_INFO FilterInfo; 
     FILTER_STATE FilterState; 

     char szName[256]; 

     pFilter->GetState(200, &FilterState); 
     pFilter->QueryFilterInfo(&FilterInfo); 
     WideCharToMultiByte(CP_ACP, 0, FilterInfo.achName, -1, szName, 256, 0, 0); 

     sprintf(debugString, "Filter: %s, %d", szName, FilterState); 

     DebugLog(debugString); 

     SAFE_RELEASE(FilterInfo.pGraph); 
     SAFE_RELEASE(pFilter); 
    } 

    SAFE_RELEASE(pEnum); 

    if (hr == S_OK) 
    { 
     break; 
    } 
} 

sprintf(debugString, "mediaControl->Stop()"); 
DebugLog(debugString); 

mediaControl->Stop(); 

합니다. 따라서 필터가 올바르게 연결되어 있고 모든 필터가 실행 중인데 왜 "깨진"기계에서 그래프가 완성되지 않습니까?

업데이트 : Roman R.의 제안에 따라 깨진 기계의 필터 그래프에서 CTransInPlaceFilter을 제거했으며 그래프가 성공적으로 완료되었습니다. CTransInPlaceFilter이 연결되면 CPU 사용량이 0으로 떨어집니다. 그래서 다음 코드가 일부 컴퓨터에서는 작동하지만 다른 컴퓨터에서는 작동하지 않는 이유가 지금은 있습니다. CTransInPlaceFilter에 디버그 로깅을 추가하여 어떤 작업이 진행되고 있는지 (또는 진행되지 않는지) 알아 보겠습니다.


솔루션 : 로마 R. (나 자신을 반복하고있어 같은 느낌 : P)에 의해 제안 된 것과 같은 문제가 교착 상태 었죠. 깨진 머신에는 모두 하나의 CPU/코어가 있었는데, 작업하는 머신에는 여러 개의 CPU/코어가있었습니다. 응용 프로그램은 원본 비디오 당 스레드, 병합 스레드 및 대상 스레드로 구성됩니다.

소스 그래프는 IMediaSample에서 데이터를 검색하고 CQueue<BYTE*>에 배치하기 위해 필터 그래프를 실행합니다 (필터 그래프도 자체 스레드에서 실행된다고 가정합니다).

병합 스레드는 소스를 반복하고 소스 CQueue<BYTE*>에서 샘플 데이터를 검색하고 프레임을 단일 이미지로 병합 한 다음 대상 스레드가 사용하는 CQueue<BYTE*>으로 전송합니다.

대상 스레드는 비디오/오디오를 인코딩하기 위해 다른 필터 그래프를 실행합니다. 여유 공간이

풋에 CQueue<BYTE*> 블록 될 때까지. 병합 스레드가 항목을 제거하기 때문에 일반적으로 괜찮습니다. 그러나 단일 CPU/코어 시스템에서는 병합 스레드가 소스 스레드에 의해 차단되었습니다.

긴 이야기는 짧은 여기 Sleep(0); 및 소스 스레드가 병합 스레드와 문제에 굴복하는이 허용는 해결 될 것으로 보인다.

+1

코드 스 니펫이 문제와 관련 없을 것 같습니다. 먼저 필터 그래프를 생성해야합니다. 그런 다음 그래프를 실행하기 전에 효과적인 토폴로지를 검사하여 내부의 내용을 확인해야합니다. 이 단계에서 시스템 간의 차이점을 볼 수 있습니다. 그러면 스트리밍이 불완전하게되는 것을 볼 수 있습니다. –

+1

그래프를 보면 스파이가 작동합니다. 그러나 스트리밍이 진행되는 동안 창 메시지를 펌핑하지 않으면 스파이 및 그래프 원격 도구가 멈 춥니 다. 따라서 코드에 더 많은 문제가 있습니다 (물론 치명적이지는 않지만 메시지 펌프는 좋은 아이디어입니다). –

답변

2

재생 완료 내부 하류 필터에 의해 중계되는 스트림 소스로부터 스트림 통지 송신단 포함 렌더러에 수집 한 다음, 결합 된 애플리케이션에보고된다. 따라서, 성공적인 완성은 필터 그래프의 모든 참여자에 따라 달라집니다.

그래프의 토폴로지를 발견했으며 다른 컴퓨터의 토폴로지를 비교해야합니다. 거기에 차이가 있으면 어떤 필터가 완료 알림을 잃을 지 제안 할 수 있습니다.

그러나, 토폴로지 정확하게 일치하는 경우에도, 일부 필터는 다른 이유로 다르게 행동 할 수있다. 특히 그래프에 사용자 정의 필터를 지정하면 알림이 손실되고 그래프가 완료되지 않을 가능성이 큽니다. 데이터 처리를 멈추고 거기에서 유휴 상태가됩니다 (CPU 사용량이 0으로 떨어지거나 일부 처리가 여전히 진행 중인지 여부를 확인하려는 또 다른 문제입니다.이 경우 문제를 교착 상태로 다시 지정할 수 있습니다). 당신이 더 많거나 적은 쉽게이 문제를 접근 할 수

뭔가 정확히에 문제를 제공하는 필터를 식별하기 위해 그래프 떨어져 필터를 절단 시작하는 것입니다.이 그래프를 시도하면 위반자를 찾을 수 있습니다.

File Source -> MPEG Demux -> MPEG4 Decoder -> Color Space Converter -> Null Render 
File Source -> MPEG Demux -> MPEG4 Decoder -> Null Render 
File Source -> MPEG Demux -> Null Render 
+0

그래, 어딘가에있어. 그래프에서 CTransInPlaceFilter를 제거하고 성공적으로 완료했습니다. 아직 필터가 일부 컴퓨터에서는 작동하지만 다른 컴퓨터에서는 작동하지 않는 이유는 확실하지 않습니다. 자세한 내용으로 업데이트 된 질문입니다. –

+0

이 필터의'IPin :: EndOfStream' 주변을 검사해야합니다. 뭔가 잘못 됐어. –

+0

나는 IPin :: EndOfStream을 구현하지 않았다는 것을 알 수있는 한, 어디서나베이스에 의존했다. 그러나 네 번 호출 된'CTransInPlaceFilter :: Transform' 메서드 만 보았으므로 교착 상태에 관한 것이있을 것이라고 생각합니다. 내 작업 기계에서 프레임 수와 관련된 적절한 횟수라는 메서드를 참조하십시오. –

2

모든 것을 보지 않고 말하기는 매우 어렵습니다. DS 필터를 개발할 때는 GraphStudio와 FilterGraph Spy을 많이 사용했습니다.

일반적인 실수는 대상 컴퓨터에서 사용할 수없는 "자동 필터"를 사용하는 것입니다. 비디오가 h264이고 원시 RGB를 읽으려고하면 DS가 자동으로 디코더 필터와 색 공간 변환을 제공합니다. 많은 중간 필터는 코드에서 알아 차리지 않고도 생성됩니다. 그렇기 때문에 그래프를 시각적 도구로 덤핑하고 모든 것이 유선 상태인지 확인하는 것이 매우 중요합니다.

내 생각 엔 그 '매직 필터'중 하나 이상이 배포 서버에 존재하지 않는다는 것입니다. 시도 할 수있는 일은 GraphStudio를 서버에서 직접 사용하고 프로그래밍 방식으로하는 것처럼 모든 것을 연결하고 거기에서 실패하는 방법과 이유를 확인하는 것입니다.

+0

팁 주셔서 감사합니다. 나는 그 도구를보고 내가 찾을 수있는 것을 보게 될 것이다. –

관련 문제