3. 기초 사항

이 장에서는 GStreamer의 기본 개념에 대해 설명합니다. 이 장에서 설명하는 기본 개념이 이 책에서 나오는 앞으로 나올 부분을 이해하는데 있어 상당히 중요합니다. 이 장 이후부터는 독자가 기본 개념을 잘 숙지하고 있다는 것을 전제합니다.


3.1. 엘리먼트(Element)

엘리먼트는 GStreamer에서 가장 중요한 객체입니다. 보통 서로 엘리먼트를 연결하여, 그 사이로 데이터가 흐르게 만들게 될 것입니다. 하나의 엘리먼트는 하나의 특정한 기능을 합니다. 예를 들어 파일 읽기, 파일 디코딩, 아웃풋 된 파일을 사운드 카드에 쓰기 등의 기능을 각각의 엘리먼트가 수행합니다. 여러 엘리먼트를 연결하려면, 사용자는 파이프 라인이라는 것을 만들어야합니다. 파이프 라인은 명확한 특정한 업무를 수행합니다. 파이프 라인이 수행하는 업무의 예로는 미디어 플레이나 캡쳐가 있습니다. GStreamer는 상당히 많은 엘리먼트를 기본 포함하고 있고, 이를 통해 상당히 다양한 미디어 애플리케이션 개발이 가능합니다. 또한, 필요에 의해 엘리먼트는 직접 생성할 수 있습니다. 엘리먼트 생성 방법은 GStreamer PlugIn Writer’s Guide에 잘 나와 있습니다.

 

3.2. 패드(Pads)

엘리먼트의 패드는 다른 엘리먼트와 연결에서 사용하는 입력과 출력입니다. 패드는 엘리먼트 간 연결을 협상하고, 데이터를 전송하는 역할을 합니다. 패드를 엘리먼트와 다른 엘리먼트를 연결하는 플러그(Plug)나 포트(Port)로 볼 수 있습니다. 그리고 패드를 통해 연결 된 엘리먼트 간의 데이터가 전송됩니다. 패드는 전송 가능한 데이터를 제한하는 분명한 데이터 핸들링 능력을 가지고 있습니다. 패드 간 전송할 데이터에 호환성이 있다면, 2개의 패드만으로도 연결을 생성할 수 있습니다. 패드 간의 데이터 타입 협상을 위해 호환성 협상(caps negotiation)라고 불리는 단계를 사용합니다. 데이터 타입은 GstCaps에 설명되어 있습니다.

비유가 여기에서 도움을 줍니다. 패드는 실생활에 사용되는 기기에서 잭이나 플러그와 유사합니다. 이러한 예를 생각해봅시다. 앰프와 DVD 플레이어, 비디오 프로젝트로 구성된 홈 시어터 시스템이 있습니다. 플레이어와 앰프는 연결 가능한 오디오 잭을 가지고 있기 때문에 플레이어를 앰프에 연결 할 수 있습니다. 그리고 프로젝터와 플레이어는 호환 가능한 비디오 잭을 가지고 있기 때문에, 프로젝터를 플레이어에 연결 할 수 있습니다. 프로젝터와 앰프는 다른 타입의 잭을 가지고 있기 때문에 두 기기를 연결할 수 없습니다. GStreamer의 패드는 홈 시어터 시스템의 잭과 같은 역할을 수행합니다.

대부분, 엘리먼트 간에서 데이터는 한 방향으로 흐릅니다. 하나의 엘리먼트에 있는 하나 이상의 소스 패드로부터 데이터가 나와서, 다른 엘리먼트의 하나 이상의 싱크 패드로 데이터가 들어갑니다. 소스와 싱크 엘리먼트는 각각 소스와 싱크 패드를 가진 엘리먼트를 말합니다. 데이터는 보통 버퍼(GstBuffer객체에 설명)와 이벤트(GstEvent 객체에 설명)를 의미합니다. 


3.3. 빈(Bins)과 파이프 라인(Pipelines)

빈은 엘리먼트를 모으기 위한 컨테이너이다. 빈 자체가 엘리먼트의 서브 클래스이기 때문에, 빈을 엘리먼트처럼 제어할 수 있다. 그렇게 함으로써 애플리케이션의 복잡성을 많이 감소시킬 수 있다. 예를 들어, 빈 자체의 상태(state)를 변경하는 것으로 빈에 속해 있는 모든 엘리먼트의 상태를 변경할 수 있다. 빈은 또한 빈에 속한 자식(에러/태그/EOS 메시지와 같은)으로부터 오는 메시지를 포워딩 해준다.

그림 3 – 1. 간단한 Ogg 플레이어를 위한 GStreamer 파이프 라인그림 3 – 1. 간단한 Ogg 플레이어를 위한 GStreamer 파이프 라인

파이프 라인은 최상위 빈이다. 파이프 라인은 애플리케이션을 위해 버스를 제공하고, 파이프 라인에 속한 자식을 위해 메시지 동기화를 제공한다. 독자가 파이프 라인을 PAUSED나 PLAYING 상태로 설정하면, 데이터의 흐름이 시작되고 미디어 처리가 시작될 것 입니다. 한번 시작되면, 사용자가 파이프 라인을 멈추거나 데이터 스트림의 끝에 도달할 때 까지 파이프 라인은 독립된 스레드에서 동작할 것 입니다.

 

3.4. 통신(Communication)

그림 3 – 2. GStreamer 파이프 라인에서 다양한 통신의 흐름그림 3 – 2. GStreamer 파이프 라인에서 다양한 통신의 흐름

GStreamer는 통신과 애플리케이션과 파이프 라인간의 데이터 교환을 위한 몇 가지 메카니즘을 제공합니다.

  • 버퍼(buffers)는 파이프 라인 안의 엘리먼트간 스트리밍 데이터 전달을 위한 객체입니다. 버퍼는 소스에서 싱크로 데이터가 전송됩니다. (다운스트림 : downstream)
  • 이벤트(events)는 엘리먼트간이나 애플리케이션에서 엘리먼트로 전송되는 객체입니다. 이벤트는 업스트림이나 다운스트림으로 이동이 가능합니다. 다운스트림 이벤트는 데이터 흐름에 동기화 할 수 있습니다.
  • 메시지(messages)는 파이프 라인의 메시지 버스에서 엘리먼트에 의해 발생되는 객체입니다. 메시지는 파이프 라인의 버스를 통해 애플리케이션으로 전달됩니다. 메시지는 동기적으로 메시지를 생성한 엘리먼트의 스트리밍 스레드 컨텍스트에서 가로챌 수 있습니다. 그러나, 보통 애플리케이션 메인 스레드에서 비동기적으로 처리를 합니다. 메세지는 에러, 태그, 상태 변화, 버퍼링 상태, 리다이렉트 등의 정보를 엘리먼트에서 애플레이케이션으로 스레드에 안전한 방법으로 전송이 됩니다.
  • 퀴리(queries)는 파일 총 재생 시간이나 현재 플레이 시간을 파이프 라인에 요청 하는 것을 가능하게 해줍니다. 쿼리는 항상 동기적으로 응답을 받아야합니다. 엘리먼트 역시 연결된 엘리먼트에게 정보(파일 사이즈나 파일 총 재생 시간 같은)를 쿼리로 요청할 수 있습니다.쿼리는 파이프 라인에서 업/다운 스트림 방식으로 사용할 수 있지만, 업스트림 쿼리가 더 일반적입니다.
이 글에 사용한 모든 이미지는 GStreamer Application Development Manual가 출처입니다.


Posted by _유부남J군_