DirectShow DirectShow 에 대해 필터 그래프의 데이터 플로우 샘플과 할당자   [목차열람] [주소복사] [슬롯비우기]
샘플과 할당자
 
Microsoft DirectX 9.0

샘플과 할당자

핀이 다른 핀에 미디어 데이터를 보내는 경우, 핀은 메모리 버퍼에의 직접적인 포인터를 건네주는 것은 아니다. 그 대신에, 메모리를 관리하는 COM 개체의 포인터를 건네준다. 이 개체는,"미디어 샘플" 로 불려IMediaSample 인터페이스를 공개한다. 수신 핀은,IMediaSample::GetPointer ,IMediaSample::GetSize , 및 IMediaSample::GetActualDataLength 등의 IMediaSample 메서드를 호출하는 것에 의해 메모리 버퍼에 액세스 한다.

샘플은, 항상, 출력 핀으로부터 입력 핀으로 다운 스트림으로 이동한다. 푸쉬 모델에서는, 출력 핀은, 입력 핀에 대해서 IMemInputPin::Receive 메서드를 호출하는 것에 의해, 샘플을 송신한다. 입력 핀은, 데이터를 동기적으로 (즉 완전하게 Receive 메서드내에서) 처리하는지, 워커 thread로 비동기적으로 처리한다. 입력 핀은, 리소스를 기다릴 필요가 있는 경우는,Receive 메서드내에서 블록 할 수 있다.

미디어 샘플의 생성과 관리를 실시하는 이제 1 개의 COM 개체가 "할당자" 이다. 할당자는 IMemAllocator 인터페이스를 공개한다. 필터는 버퍼가 하늘의 미디어 샘플이 필요하게 되면IMemAllocator::GetBuffer 메서드를 호출한다. 이 메서드는 샘플의 포인터를 돌려준다. 각 핀 접속은 1 개의 할당자를 공유한다. 2 개의 핀을 접속하는 경우, 어느 쪽의 필터가 할당자를 제공할지가 결정된다. 핀은, 버퍼의 수나 각 버퍼의 사이즈 등, 할당자에 관한 프로퍼티도 설정한다. 더 자세한 정보는, 「필터의 접속」 및 「할당자의 조정」을 참조할것.

다음 그림은 할당자, 미디어 샘플, 필터의 관계를 나타내고 있다.

미디어 샘플과 할당자

미디어 샘플의 참조 카운트

할당자는 유한의 샘플의 풀을 생성 한다. 어떤 시점으로, 사용중인 샘플도 있으면,GetBuffer 의 호출로 이용할 수 있는 샘플도 있다. 할당자는 참조 카운트를 사용해 샘플을 추적한다. GetBuffer 메서드는, 참조 카운트를 1 으로 해 샘플을 돌려준다. 참조 카운트가 0 이 되면 샘플은 할당자의 풀로 돌아가, 다음의 GetBuffer 의 호출로 이용할 수 있다. 참조 카운트가 0 보다 클 따름, 샘플은 GetBuffer 로 이용할 수 없다. 할당자에 속하는 모든 샘플이 사용중인 경우,GetBuffer 메서드는 샘플이 이용 가능하게 될 때까지 블록 한다.

예를 들어, 입력 핀이 샘플을 받는 경우를 생각해 본다. 입력 핀이 샘플을 Receive 메서드내에서 동기적으로 처리하는 경우, 입력 핀은 참조 카운트를 인크리먼트(increment) 하지 않는다. Receive 가 돌아오면 출력 핀은 샘플을 릴리즈 해, 참조 카운트는 0 이 되어, 샘플은 할당자의 풀로 돌아간다. 한편, 입력 핀이 워커 thread상에서 샘플을 처리하는 경우, 입력 핀은 Receive 메서드를 멀어지기 전에 참조 카운트를 인크리먼트(increment) 한다. 이 때 참조 카운트는 2 가 된다. 출력 핀이 샘플을 릴리즈 하면, 카운트는 1 이 되지만, 샘플은 아직 풀로 돌아가지 않는다. 워커 thread는, 샘플의 처리를 종료 하면,Release 를 호출해 샘플을 릴리즈 한다. 이 때 샘플은 풀로 돌아간다.

핀은, 샘플을 받으면 데이터를 다른 샘플에 복사 하거나 원의 샘플을 변경해 다음의 필터에 보내거나 할 수가 있다. 잠재적으로, 샘플은 그래프 전체를 이동할 가능성이 있어, 각 필터는 순서에 AddRefRelease 를 호출한다. 따라서, 출력 핀은 Receive 를 호출한 다음에 샘플을 재이용하지 않게 해야 한다. 다운 스트림의 필터가 샘플을 사용하고 있는 경우가 있기 때문이다. 출력 핀은 항상 GetBuffer 를 호출해 새로운 샘플을 얻어올 필요가 있다.

이 메카니즘에서는 필터가 같은 버퍼를 재이용하기 위해(때문에), 메모리 할당의 양이 적어도 된다. 또, 할당자는 사용 가능한 샘플의 리스트를 보관 유지하고 있기 (위해)때문에, 아직 처리가 끝나지 않은 데이터가 필터에 의해 잘못해 덧쓰기되는 것을 방지할 수 있다.

필터가 입력용과 출력용으로 다른 할당자를 사용하는 일도 가능하다. 필터는 입력 데이터를 전개하는 (데이터의 압축 해제 등) 경우에, 이러한 처리를 실시하는 일이 있다. 출력이 입력보다 크지 않은 경우, 필터는 데이터를 새로운 샘플에 복사 하지 않고, 원의 장소에서 처리할 수 있다. 그 경우, 2 개 이상의 핀 접속으로 1 개의 할당자를 공유할 수 있다.

할당자의 위탁과 데코밋트

필터가 최초로 할당자를 생성 하는 경우, 할당자는 메모리 버퍼를 아무것도 예약하고 있지 않다. 이 시점에서는,GetBuffer 메서드를 호출하면 실패한다. 스트리밍이 시작되면 출력 핀은 IMemAllocator::Commit 을 호출해, 할당자를 "위탁" 해 메모리를 할당한다. 이것으로 핀은 GetBuffer 를 호출할 수가 있다.

스트리밍이 종료 하면, 핀은 IMemAllocator::Decommit 를 호출해, 할당자를 "데코밋트" 하는. 할당자가 다시 위탁될 때까지, 이 이후의 GetBuffer 의 호출은 모두 실패한다. 또, 현재, 샘플을 기다려 블록 하고 있는 GetBuffer 의 호출이 있는 경우, 그 호출은 즉시 에러 코드를 돌려준다. Decommit 메서드는, 처리에 의해, 메모리를 릴리즈 하는 경우와 릴리즈 하지 않는 경우가 있다. 예를 들어,CMemAllocator 클래스는, 데콘스트라크타메솟드가 메모리를 릴리즈 할 때까지 대기한다.

↑TOP