본문 바로가기
IT와 개발/GStreamer Study

Clocks and synchronization in GStreamer

by 도서 임보자 2024. 6. 7.

복잡한 미디어를 재생할 때 각 사운드 및 비디오 샘플은 특정 시간에 특정 순서로 재생되어야 합니다. 이를 위해 GStreamer는 동기화 메커니즘을 제공합니다.

GStreamer는 다음 사용 사례를 지원합니다.

  • 재생 속도보다 빠른 액세스가 가능한 비실시간 소스입니다. 이는 파일에서 미디어를 읽고 동기화된 방식으로 재생하는 경우입니다. 이 경우 오디오, 비디오, 자막 등 여러 스트림을 동기화해야 합니다.
  • 여러 라이브 소스에서 캡처하고 동기화된 다중화/믹싱 미디어입니다. 이는 마이크/카메라에서 오디오 및 비디오를 녹음하고 이를 파일로 다중화하여 저장하는 일반적인 사용 사례입니다.
  • 버퍼링을 사용하여 (느린) 네트워크 스트림에서 스트리밍합니다. 이는 HTTP를 사용하여 스트리밍 서버의 콘텐츠에 액세스하는 일반적인 웹 스트리밍 사례입니다.
  • 라이브 소스에서 캡처하고 구성 가능한 레이턴시로 재생합니다. 예를 들어 카메라에서 캡처하고 효과를 적용하고 결과를 표시할 때 사용됩니다. UDP를 사용하는 네트워크를 통해 대기 시간이 짧은 콘텐츠를 스트리밍할 때도 사용됩니다
  • 사전 녹화된 콘텐츠를 동시에 실시간 캡처하고 재생할 수 있습니다. 이는 이전에 녹음된 오디오를 재생하고 새 샘플을 녹음하는 오디오 녹음의 경우에 사용됩니다. 목적은 새 오디오를 이전에 녹음된 데이터와 완벽하게 동기화하는 것입니다.

GStreamer는 다음 섹션에서 볼 수 있듯이 GstClock 객체, 버퍼 타임스탬프 및 SEGMENT 이벤트를 사용하여 파이프라인의 스트림을 동기화합니다.

 

Clock running-time

일반적인 컴퓨터에는 시스템 시간, 사운드 카드, CPU 성능 카운터 등 시간 소스로 사용할 수 있는 소스가 많이 있습니다. 이러한 이유로 GStreamer에는 사용 가능한 GstClock 구현이 많이 있습니다. Clock time은 0이나 다른 알려진 값에서 시작할 필요가 없습니다. 일부 clock들은 특정 시작 날짜부터 계산을 시작하고 다른 clock들은 마지막 재부팅 날짜부터 계산을 시작합니다.


GstClock은 gst_clock_get_time()을 사용하여 해당 clock에 따른 절대 시간 (absolute-time)을 반환합니다. Clock의 절대 시간 (또는 clock time)은 단조롭게 증가합니다.


실행 시간 (running-time)기본 시간 (base-time)이라고 하는 절대 시간의 이전 스냅샷과 다른 절대 시간 간의 차이입니다.

running-time = absolute-time - base-time

 

GStreamer GstPipeline 객체는 PLAYING 상태로 전환될 때 GstClock 객체와 기본 시간을 유지합니다. 파이프라인은 선택된 기본 시간과 함께 파이프라인의 각 element에 선택된 GstClock에 대한 핸들을 제공합니다. 파이프라인은 실행 시간이 PLAYING 상태에서 소요된 총 시간을 반영하는 방식으로 기본 시간을 선택합니다. 결과적으로 파이프라인이 PAUSED되면 실행 시간은 그대로 유지됩니다.

파이프라인의 모든 개체는 동일한 clock과 기본 시간을 가지므로 모두 파이프라인 시계에 따라 실행 시간을 계산할 수 있습니다.

 

Buffer running-time

버퍼 실행 시간을 계산하려면 버퍼 타임스탬프와 버퍼 앞에 오는 SEGMENT 이벤트가 필요합니다. 먼저 SEGMENT 이벤트를 GstSegment 객체로 변환한 다음 gst_segment_to_running_time() 함수를 사용하여 버퍼 실행 시간 계산을 수행할 수 있습니다.


이제 동기화는 clock이 동일한 실행 시간에 도달할 때 특정 실행 시간을 가진 버퍼가 재생되는지 확인하는 문제입니다. 일반적으로 이 작업은 sink element에 의해 수행됩니다. 또한 이러한 element는 구성된 파이프라인의 latency를 고려하여 파이프라인 clock에 동기화하기 전에 이를 버퍼 실행 시간에 추가해야 합니다.


실시간이 아닌 source의 타임스탬프 버퍼는 실행 시간이 0부터 시작됩니다. Flushing seek 후 실행 시간 0부터 버퍼를 다시 생성합니다.


실시간 source는 버퍼의 첫 번째 바이트가 캡처된 파이프라인 실행 시간과 일치하는 실행 시간으로 버퍼에 타임스탬프를 찍어야 합니다.

 

Buffer stream-time

스트림의 위치라고도 알려진 버퍼 스트림 시간은 0과 미디어의 총 지속 시간 사이의 값이며 버퍼 타임스탬프와 이전 SEGMENT 이벤트에서 계산됩니다.


스트림 시간은 다음에서 사용됩니다.

  • POSITION 쿼리를 사용하여 스트림의 현재 위치를 보고합니다.
  • Seek 이벤트 및 쿼리에 사용되는 위치입니다.
  • 제어된 값을 동기화하는 데 사용되는 위치입니다.

스트림 시간은 스트림을 동기화하는데 사용되지 않으며 이는 실행 시간으로만 수행됩니다.

 

Time overview

다음은 GStreamer에서 사용되는 다양한 타임라인에 대한 개요입니다.


아래 이미지는 100ms 샘플을 재생하고 50ms에서 100ms 사이의 부분 (running time 기준)을 반복할 때 파이프라인의 다양한 시간을 나타냅니다.

 

버퍼의 실행 시간이 clock 시간에 따라 항상 단조롭게 증가하는 방식을 확인할 수 있습니다. 버퍼는 실행 시간이 clock 시간 - 기본 시간과 같을 때 재생됩니다. 스트림 시간은 스트림의 위치를 ​​나타내며 반복 시 뒤로 이동합니다.

 

Clock providers

Clock 공급자는 GstClock 객체를 제공할 수 있는 파이프라인의 element입니다. Clock 객체는 element가 PLAYING 상태에 있을 때 단조롭게 증가하는 절대 시간을 리포트해야 합니다. Element가 PAUSED인 동안 clock을 일시 중지할 수 있습니다.


Clock 공급자는 특정 속도로 미디어를 재생하기 위해 존재하며 이 속도가 시스템 clock 속도와 반드시 동일할 필요는 없습니다. 예를 들어, 사운드 카드는 44.1kHz로 재생할 수 있지만 이것이 시스템 clock에 따라 정확히 1초 후에 사운드 카드가 44100 샘플을 재생했다는 의미는 아닙니다. 이는 근사치에 의한 사실입니다. 실제로 오디오 장치에는 노출할 수 있는 재생된 샘플 수를 기반으로 하는 내부 clock이 있습니다.


내부 clock이 있는 element를 동기화해야 하는 경우 파이프라인 clock에 따른 시간이 내부 clock에 따라 발생하는 시기를 추정해야 합니다. 이를 추정하려면 clock을 파이프라인 clock에 종속시켜야 합니다.


파이프라인 clock이 정확히 element의 내부 clock인 경우 element는 종속 단계를 건너뛰고 파이프라인 clock을 직접 사용하여 재생을 예약할 수 있습니다. 이는 더 빠르고 정확할 수 있습니다. 따라서 일반적으로 오디오 입력 또는 출력 장치와 같은 내부 clock이 있는 element는 파이프라인의 clock 공급자가 됩니다.


파이프라인이 PLAYING 상태로 전환되면 sink에서 source까지 파이프라인의 모든 element를 ​​살펴보고 각 element에 clock을 제공할 수 있는지 묻습니다. Clock를 제공할 수 있는 마지막 element는 파이프라인에서 clock 공급자로 사용됩니다. 이 알고리즘은 일반적인 재생 파이프라인의 오디오 sink의 clock과 일반적인 capture 파이프라인의 source element의 clock을 선호합니다.


파이프라인의 clock 및 clock 제공자에 대해 알려주는 몇 가지 bus 메시지가 있습니다. Bus의 NEW_CLOCK 메시지를 보면 파이프라인에서 어떤 clock이 선택 되었는지 확인할 수 있습니다. Clock 공급자가 파이프라인에서 제거되면 CLOCK_LOST 메시지가 게시되고 애플리케이션은 PAUSED 상태로 이동했다가 다시 PLAYING 상태로 돌아가 새 clock을 선택해야 합니다.

 

Latency

Latency는 타임스탬프 X에서 캡처된 샘플이 sink에 도달하는데 걸리는 시간입니다. 이 시간은 파이프라인의 clock을 기준으로 측정됩니다. Clock에 대해 동기화하는 유일한 element가 sink인 파이프라인의 경우 다른 element가 버퍼를 지연시키지 않으므로 latency는 항상 0입니다.


Live source가 있는 파이프라인의 경우 주로 live source 작동 방식으로 인해 latency가 발생합니다. 오디오 source를 고려하면 시간 0에서 첫 번째 샘플 캡처가 시작됩니다. Source가 44100Hz에서 한 번에 44100개의 샘플을 버퍼로 푸시하는 경우, 1초 후에 버퍼를 수집하게 됩니다. 버퍼의 타임스탬프는 0이고 시간은 현재 clock의 시간이 1초 이상이면 너무 늦기 때문에 sink가 이 버퍼를 삭제합니다. Sink에 latency 보상이 없으면 모든 버퍼가 삭제됩니다.

 

Latency compensation

파이프라인이 PLAYING 상태로 전환되기 전에 clock을 선택하고 기본 시간을 계산하는 것 외에도 파이프라인의 latency를 계산합니다. 파이프라인의 모든 sink에 대해 LATENCY 쿼리를 수행하여 이를 수행합니다. 그런 다음 파이프라인은 파이프라인의 최대 latency를 선택하고 이를 LATENCY 이벤트로 구성합니다.


모든 sink element는 LATENCY 이벤트의 값만큼 재생을 지연시킵니다. 모든 sink는 동일한 시간만큼 지연되므로 상대적으로 동기화됩니다.

 

Dynamic Latency

파이프라인에 element를 추가/제거하거나 element 속성을 변경하면 파이프라인의 latency가 변경될 수 있습니다. Element는 버스에 LATENCY 메시지를 게시하여 파이프라인의 latency 변경을 요청할 수 있습니다. 그런 다음 애플리케이션은 새로운 latency를 쿼리하고 재배포할지 여부를 결정할 수 있습니다. 파이프라인에서 latency를 변경하면 시각적 또는 청각적 결함이 발생할 수 있으므로 허용되는 경우에만 애플리케이션에서 수행해야 합니다.

 

 

원문: Clocks and synchronization in GStreamer

 

Clocks and synchronization in GStreamer

Clocks and synchronization in GStreamer When playing complex media, each sound and video sample must be played in a specific order at a specific time. For this purpose, GStreamer provides a synchronization mechanism. GStreamer provides support for the foll

gstreamer.freedesktop.org

 

반응형

'IT와 개발 > GStreamer Study' 카테고리의 다른 글

Dynamic Controllable Parameters  (1) 2024.06.21
Buffering  (1) 2024.06.14
Interfaces  (3) 2024.05.31
Metadata  (91) 2024.05.24
Position tracking and seeking  (0) 2024.05.17