비디오 파일에서 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
입니다. 우리의 CTransInPlaceFilter
의 CheckInputType
방법에서 우리는 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);
및 소스 스레드가 병합 스레드와 문제에 굴복하는이 허용는 해결 될 것으로 보인다.
코드 스 니펫이 문제와 관련 없을 것 같습니다. 먼저 필터 그래프를 생성해야합니다. 그런 다음 그래프를 실행하기 전에 효과적인 토폴로지를 검사하여 내부의 내용을 확인해야합니다. 이 단계에서 시스템 간의 차이점을 볼 수 있습니다. 그러면 스트리밍이 불완전하게되는 것을 볼 수 있습니다. –
그래프를 보면 스파이가 작동합니다. 그러나 스트리밍이 진행되는 동안 창 메시지를 펌핑하지 않으면 스파이 및 그래프 원격 도구가 멈 춥니 다. 따라서 코드에 더 많은 문제가 있습니다 (물론 치명적이지는 않지만 메시지 펌프는 좋은 아이디어입니다). –